]> source.dussan.org Git - poi.git/commitdiff
#64004 - Replace clone() with copy constructor - mainly HSSF classes
authorAndreas Beeker <kiwiwings@apache.org>
Sun, 22 Dec 2019 21:44:45 +0000 (21:44 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sun, 22 Dec 2019 21:44:45 +0000 (21:44 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1871911 13f79535-47bb-0310-9956-ffa450edef68

370 files changed:
src/integrationtest/org/apache/poi/TestAllFiles.java
src/integrationtest/org/apache/poi/hssf/usermodel/RecordsStresser.java
src/java/org/apache/poi/common/Duplicatable.java [new file with mode: 0644]
src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java
src/java/org/apache/poi/ddf/EscherContainerRecord.java
src/java/org/apache/poi/ddf/EscherRecord.java
src/java/org/apache/poi/ddf/EscherTextboxRecord.java
src/java/org/apache/poi/ddf/UnknownEscherRecord.java
src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/DummyRecordBase.java
src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/LastCellOfRowDummyRecord.java
src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingCellDummyRecord.java
src/java/org/apache/poi/hssf/eventusermodel/dummyrecord/MissingRowDummyRecord.java
src/java/org/apache/poi/hssf/model/InternalSheet.java
src/java/org/apache/poi/hssf/model/RecordStream.java
src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java
src/java/org/apache/poi/hssf/record/ArrayRecord.java
src/java/org/apache/poi/hssf/record/AutoFilterInfoRecord.java
src/java/org/apache/poi/hssf/record/BOFRecord.java
src/java/org/apache/poi/hssf/record/BackupRecord.java
src/java/org/apache/poi/hssf/record/BlankRecord.java
src/java/org/apache/poi/hssf/record/BookBoolRecord.java
src/java/org/apache/poi/hssf/record/BoolErrRecord.java
src/java/org/apache/poi/hssf/record/BottomMarginRecord.java
src/java/org/apache/poi/hssf/record/BoundSheetRecord.java
src/java/org/apache/poi/hssf/record/CFHeader12Record.java
src/java/org/apache/poi/hssf/record/CFHeaderBase.java
src/java/org/apache/poi/hssf/record/CFHeaderRecord.java
src/java/org/apache/poi/hssf/record/CFRule12Record.java
src/java/org/apache/poi/hssf/record/CFRuleBase.java
src/java/org/apache/poi/hssf/record/CFRuleRecord.java
src/java/org/apache/poi/hssf/record/CRNCountRecord.java
src/java/org/apache/poi/hssf/record/CRNRecord.java
src/java/org/apache/poi/hssf/record/CalcCountRecord.java
src/java/org/apache/poi/hssf/record/CalcModeRecord.java
src/java/org/apache/poi/hssf/record/CellRecord.java
src/java/org/apache/poi/hssf/record/CodepageRecord.java
src/java/org/apache/poi/hssf/record/ColumnInfoRecord.java
src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java
src/java/org/apache/poi/hssf/record/ContinueRecord.java
src/java/org/apache/poi/hssf/record/CountryRecord.java
src/java/org/apache/poi/hssf/record/DBCellRecord.java
src/java/org/apache/poi/hssf/record/DConRefRecord.java
src/java/org/apache/poi/hssf/record/DSFRecord.java
src/java/org/apache/poi/hssf/record/DVALRecord.java
src/java/org/apache/poi/hssf/record/DVRecord.java
src/java/org/apache/poi/hssf/record/DateWindow1904Record.java
src/java/org/apache/poi/hssf/record/DefaultColWidthRecord.java
src/java/org/apache/poi/hssf/record/DefaultRowHeightRecord.java
src/java/org/apache/poi/hssf/record/DeltaRecord.java
src/java/org/apache/poi/hssf/record/DimensionsRecord.java
src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java
src/java/org/apache/poi/hssf/record/DrawingRecord.java
src/java/org/apache/poi/hssf/record/DrawingRecordForBiffViewer.java
src/java/org/apache/poi/hssf/record/DrawingSelectionRecord.java
src/java/org/apache/poi/hssf/record/EOFRecord.java
src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
src/java/org/apache/poi/hssf/record/EndSubRecord.java
src/java/org/apache/poi/hssf/record/EscherAggregate.java
src/java/org/apache/poi/hssf/record/ExtSSTRecord.java
src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java
src/java/org/apache/poi/hssf/record/ExternSheetRecord.java
src/java/org/apache/poi/hssf/record/ExternalNameRecord.java
src/java/org/apache/poi/hssf/record/FeatHdrRecord.java
src/java/org/apache/poi/hssf/record/FeatRecord.java
src/java/org/apache/poi/hssf/record/FilePassRecord.java
src/java/org/apache/poi/hssf/record/FileSharingRecord.java
src/java/org/apache/poi/hssf/record/FnGroupCountRecord.java
src/java/org/apache/poi/hssf/record/FontRecord.java
src/java/org/apache/poi/hssf/record/FooterRecord.java
src/java/org/apache/poi/hssf/record/FormatRecord.java
src/java/org/apache/poi/hssf/record/FormulaRecord.java
src/java/org/apache/poi/hssf/record/FormulaSpecialCachedValue.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/FtCblsSubRecord.java
src/java/org/apache/poi/hssf/record/FtCfSubRecord.java
src/java/org/apache/poi/hssf/record/FtPioGrbitSubRecord.java
src/java/org/apache/poi/hssf/record/GridsetRecord.java
src/java/org/apache/poi/hssf/record/GroupMarkerSubRecord.java
src/java/org/apache/poi/hssf/record/GutsRecord.java
src/java/org/apache/poi/hssf/record/HCenterRecord.java
src/java/org/apache/poi/hssf/record/HeaderFooterBase.java
src/java/org/apache/poi/hssf/record/HeaderFooterRecord.java
src/java/org/apache/poi/hssf/record/HeaderRecord.java
src/java/org/apache/poi/hssf/record/HideObjRecord.java
src/java/org/apache/poi/hssf/record/HorizontalPageBreakRecord.java
src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
src/java/org/apache/poi/hssf/record/IndexRecord.java
src/java/org/apache/poi/hssf/record/InterfaceEndRecord.java
src/java/org/apache/poi/hssf/record/InterfaceHdrRecord.java
src/java/org/apache/poi/hssf/record/IterationRecord.java
src/java/org/apache/poi/hssf/record/LabelRecord.java
src/java/org/apache/poi/hssf/record/LabelSSTRecord.java
src/java/org/apache/poi/hssf/record/LbsDataSubRecord.java
src/java/org/apache/poi/hssf/record/LeftMarginRecord.java
src/java/org/apache/poi/hssf/record/MMSRecord.java
src/java/org/apache/poi/hssf/record/MergeCellsRecord.java
src/java/org/apache/poi/hssf/record/MulBlankRecord.java
src/java/org/apache/poi/hssf/record/MulRKRecord.java
src/java/org/apache/poi/hssf/record/NameCommentRecord.java
src/java/org/apache/poi/hssf/record/NameRecord.java
src/java/org/apache/poi/hssf/record/NoteRecord.java
src/java/org/apache/poi/hssf/record/NoteStructureSubRecord.java
src/java/org/apache/poi/hssf/record/NumberRecord.java
src/java/org/apache/poi/hssf/record/ObjRecord.java
src/java/org/apache/poi/hssf/record/ObjectProtectRecord.java
src/java/org/apache/poi/hssf/record/OldFormulaRecord.java
src/java/org/apache/poi/hssf/record/OldLabelRecord.java
src/java/org/apache/poi/hssf/record/OldSheetRecord.java
src/java/org/apache/poi/hssf/record/OldStringRecord.java
src/java/org/apache/poi/hssf/record/PageBreakRecord.java
src/java/org/apache/poi/hssf/record/PaletteRecord.java
src/java/org/apache/poi/hssf/record/PaneRecord.java
src/java/org/apache/poi/hssf/record/PasswordRecord.java
src/java/org/apache/poi/hssf/record/PasswordRev4Record.java
src/java/org/apache/poi/hssf/record/PrecisionRecord.java
src/java/org/apache/poi/hssf/record/PrintGridlinesRecord.java
src/java/org/apache/poi/hssf/record/PrintHeadersRecord.java
src/java/org/apache/poi/hssf/record/PrintSetupRecord.java
src/java/org/apache/poi/hssf/record/ProtectRecord.java
src/java/org/apache/poi/hssf/record/ProtectionRev4Record.java
src/java/org/apache/poi/hssf/record/RKRecord.java
src/java/org/apache/poi/hssf/record/RecalcIdRecord.java
src/java/org/apache/poi/hssf/record/Record.java
src/java/org/apache/poi/hssf/record/RecordBase.java
src/java/org/apache/poi/hssf/record/RecordInputStream.java
src/java/org/apache/poi/hssf/record/RefModeRecord.java
src/java/org/apache/poi/hssf/record/RefreshAllRecord.java
src/java/org/apache/poi/hssf/record/RightMarginRecord.java
src/java/org/apache/poi/hssf/record/RowRecord.java
src/java/org/apache/poi/hssf/record/SCLRecord.java
src/java/org/apache/poi/hssf/record/SSTRecord.java
src/java/org/apache/poi/hssf/record/SaveRecalcRecord.java
src/java/org/apache/poi/hssf/record/ScenarioProtectRecord.java
src/java/org/apache/poi/hssf/record/SelectionRecord.java
src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java
src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java
src/java/org/apache/poi/hssf/record/StandardRecord.java
src/java/org/apache/poi/hssf/record/StringRecord.java
src/java/org/apache/poi/hssf/record/StyleRecord.java
src/java/org/apache/poi/hssf/record/SubRecord.java
src/java/org/apache/poi/hssf/record/SupBookRecord.java
src/java/org/apache/poi/hssf/record/TabIdRecord.java
src/java/org/apache/poi/hssf/record/TableRecord.java
src/java/org/apache/poi/hssf/record/TableStylesRecord.java
src/java/org/apache/poi/hssf/record/TextObjectRecord.java
src/java/org/apache/poi/hssf/record/TopMarginRecord.java
src/java/org/apache/poi/hssf/record/UncalcedRecord.java
src/java/org/apache/poi/hssf/record/UnknownRecord.java
src/java/org/apache/poi/hssf/record/UseSelFSRecord.java
src/java/org/apache/poi/hssf/record/UserSViewBegin.java
src/java/org/apache/poi/hssf/record/UserSViewEnd.java
src/java/org/apache/poi/hssf/record/VCenterRecord.java
src/java/org/apache/poi/hssf/record/VerticalPageBreakRecord.java
src/java/org/apache/poi/hssf/record/WSBoolRecord.java
src/java/org/apache/poi/hssf/record/WindowOneRecord.java
src/java/org/apache/poi/hssf/record/WindowProtectRecord.java
src/java/org/apache/poi/hssf/record/WindowTwoRecord.java
src/java/org/apache/poi/hssf/record/WriteAccessRecord.java
src/java/org/apache/poi/hssf/record/WriteProtectRecord.java
src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
src/java/org/apache/poi/hssf/record/aggregates/ColumnInfoRecordsAggregate.java
src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java
src/java/org/apache/poi/hssf/record/aggregates/DataValidityTable.java
src/java/org/apache/poi/hssf/record/aggregates/FormulaRecordAggregate.java
src/java/org/apache/poi/hssf/record/aggregates/MergedCellsTable.java
src/java/org/apache/poi/hssf/record/aggregates/RecordAggregate.java
src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java
src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java
src/java/org/apache/poi/hssf/record/cf/ColorGradientThreshold.java
src/java/org/apache/poi/hssf/record/cf/DataBarFormatting.java
src/java/org/apache/poi/hssf/record/cf/DataBarThreshold.java
src/java/org/apache/poi/hssf/record/cf/FontFormatting.java
src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java
src/java/org/apache/poi/hssf/record/cf/IconMultiStateThreshold.java
src/java/org/apache/poi/hssf/record/cf/PatternFormatting.java
src/java/org/apache/poi/hssf/record/cf/Threshold.java
src/java/org/apache/poi/hssf/record/chart/AreaFormatRecord.java
src/java/org/apache/poi/hssf/record/chart/AreaRecord.java
src/java/org/apache/poi/hssf/record/chart/AxisLineFormatRecord.java
src/java/org/apache/poi/hssf/record/chart/AxisOptionsRecord.java
src/java/org/apache/poi/hssf/record/chart/AxisParentRecord.java
src/java/org/apache/poi/hssf/record/chart/AxisRecord.java
src/java/org/apache/poi/hssf/record/chart/AxisUsedRecord.java
src/java/org/apache/poi/hssf/record/chart/BarRecord.java
src/java/org/apache/poi/hssf/record/chart/BeginRecord.java
src/java/org/apache/poi/hssf/record/chart/CatLabRecord.java
src/java/org/apache/poi/hssf/record/chart/CategorySeriesAxisRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartEndBlockRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartEndObjectRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartFRTInfoRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartFormatRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartStartBlockRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartStartObjectRecord.java
src/java/org/apache/poi/hssf/record/chart/ChartTitleFormatRecord.java
src/java/org/apache/poi/hssf/record/chart/DatRecord.java
src/java/org/apache/poi/hssf/record/chart/DataFormatRecord.java
src/java/org/apache/poi/hssf/record/chart/DataLabelExtensionRecord.java
src/java/org/apache/poi/hssf/record/chart/DefaultDataLabelTextPropertiesRecord.java
src/java/org/apache/poi/hssf/record/chart/EndRecord.java
src/java/org/apache/poi/hssf/record/chart/FontBasisRecord.java
src/java/org/apache/poi/hssf/record/chart/FontIndexRecord.java
src/java/org/apache/poi/hssf/record/chart/FrameRecord.java
src/java/org/apache/poi/hssf/record/chart/LegendRecord.java
src/java/org/apache/poi/hssf/record/chart/LineFormatRecord.java
src/java/org/apache/poi/hssf/record/chart/LinkedDataRecord.java
src/java/org/apache/poi/hssf/record/chart/NumberFormatIndexRecord.java
src/java/org/apache/poi/hssf/record/chart/ObjectLinkRecord.java
src/java/org/apache/poi/hssf/record/chart/PlotAreaRecord.java
src/java/org/apache/poi/hssf/record/chart/PlotGrowthRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesChartGroupIndexRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesIndexRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesLabelsRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesListRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesTextRecord.java
src/java/org/apache/poi/hssf/record/chart/SeriesToChartGroupRecord.java
src/java/org/apache/poi/hssf/record/chart/SheetPropertiesRecord.java
src/java/org/apache/poi/hssf/record/chart/TextRecord.java
src/java/org/apache/poi/hssf/record/chart/TickRecord.java
src/java/org/apache/poi/hssf/record/chart/UnitsRecord.java
src/java/org/apache/poi/hssf/record/chart/ValueRangeRecord.java
src/java/org/apache/poi/hssf/record/common/ExtRst.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/common/ExtendedColor.java
src/java/org/apache/poi/hssf/record/common/FeatFormulaErr2.java
src/java/org/apache/poi/hssf/record/common/FeatProtection.java
src/java/org/apache/poi/hssf/record/common/FeatSmartTag.java
src/java/org/apache/poi/hssf/record/common/FormatRun.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/common/FtrHeader.java
src/java/org/apache/poi/hssf/record/common/PhRun.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/common/SharedFeature.java
src/java/org/apache/poi/hssf/record/common/UnicodeString.java
src/java/org/apache/poi/hssf/record/cont/ContinuableRecord.java
src/java/org/apache/poi/hssf/record/pivottable/DataItemRecord.java
src/java/org/apache/poi/hssf/record/pivottable/ExtendedPivotTableViewFieldsRecord.java
src/java/org/apache/poi/hssf/record/pivottable/PageItemRecord.java
src/java/org/apache/poi/hssf/record/pivottable/StreamIDRecord.java
src/java/org/apache/poi/hssf/record/pivottable/ViewDefinitionRecord.java
src/java/org/apache/poi/hssf/record/pivottable/ViewFieldsRecord.java
src/java/org/apache/poi/hssf/record/pivottable/ViewSourceRecord.java
src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
src/java/org/apache/poi/hssf/usermodel/HSSFChart.java
src/java/org/apache/poi/hssf/usermodel/HSSFHyperlink.java
src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java
src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java
src/java/org/apache/poi/hssf/util/LazilyConcatenatedByteArray.java
src/java/org/apache/poi/poifs/crypt/Decryptor.java
src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java
src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java
src/java/org/apache/poi/poifs/crypt/Encryptor.java
src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java
src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java
src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java
src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java
src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java
src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java
src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java
src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java
src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
src/java/org/apache/poi/poifs/crypt/xor/XORDecryptor.java
src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionHeader.java
src/java/org/apache/poi/poifs/crypt/xor/XOREncryptionVerifier.java
src/java/org/apache/poi/poifs/crypt/xor/XOREncryptor.java
src/java/org/apache/poi/ss/formula/Formula.java
src/java/org/apache/poi/ss/formula/ptg/AbstractFunctionPtg.java
src/java/org/apache/poi/ss/formula/ptg/AddPtg.java
src/java/org/apache/poi/ss/formula/ptg/Area2DPtgBase.java
src/java/org/apache/poi/ss/formula/ptg/Area3DPtg.java
src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java
src/java/org/apache/poi/ss/formula/ptg/AreaErrPtg.java
src/java/org/apache/poi/ss/formula/ptg/AreaNPtg.java
src/java/org/apache/poi/ss/formula/ptg/AreaPtg.java
src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java
src/java/org/apache/poi/ss/formula/ptg/ArrayPtg.java
src/java/org/apache/poi/ss/formula/ptg/AttrPtg.java
src/java/org/apache/poi/ss/formula/ptg/BoolPtg.java
src/java/org/apache/poi/ss/formula/ptg/ConcatPtg.java
src/java/org/apache/poi/ss/formula/ptg/ControlPtg.java
src/java/org/apache/poi/ss/formula/ptg/Deleted3DPxg.java
src/java/org/apache/poi/ss/formula/ptg/DeletedArea3DPtg.java
src/java/org/apache/poi/ss/formula/ptg/DeletedRef3DPtg.java
src/java/org/apache/poi/ss/formula/ptg/DividePtg.java
src/java/org/apache/poi/ss/formula/ptg/EqualPtg.java
src/java/org/apache/poi/ss/formula/ptg/ErrPtg.java
src/java/org/apache/poi/ss/formula/ptg/ExpPtg.java
src/java/org/apache/poi/ss/formula/ptg/FuncPtg.java
src/java/org/apache/poi/ss/formula/ptg/FuncVarPtg.java
src/java/org/apache/poi/ss/formula/ptg/GreaterEqualPtg.java
src/java/org/apache/poi/ss/formula/ptg/GreaterThanPtg.java
src/java/org/apache/poi/ss/formula/ptg/IntPtg.java
src/java/org/apache/poi/ss/formula/ptg/IntersectionPtg.java
src/java/org/apache/poi/ss/formula/ptg/LessEqualPtg.java
src/java/org/apache/poi/ss/formula/ptg/LessThanPtg.java
src/java/org/apache/poi/ss/formula/ptg/MemAreaPtg.java
src/java/org/apache/poi/ss/formula/ptg/MemErrPtg.java
src/java/org/apache/poi/ss/formula/ptg/MemFuncPtg.java
src/java/org/apache/poi/ss/formula/ptg/MissingArgPtg.java
src/java/org/apache/poi/ss/formula/ptg/MultiplyPtg.java
src/java/org/apache/poi/ss/formula/ptg/NamePtg.java
src/java/org/apache/poi/ss/formula/ptg/NameXPtg.java
src/java/org/apache/poi/ss/formula/ptg/NameXPxg.java
src/java/org/apache/poi/ss/formula/ptg/NotEqualPtg.java
src/java/org/apache/poi/ss/formula/ptg/NumberPtg.java
src/java/org/apache/poi/ss/formula/ptg/OperandPtg.java
src/java/org/apache/poi/ss/formula/ptg/OperationPtg.java
src/java/org/apache/poi/ss/formula/ptg/ParenthesisPtg.java
src/java/org/apache/poi/ss/formula/ptg/PercentPtg.java
src/java/org/apache/poi/ss/formula/ptg/PowerPtg.java
src/java/org/apache/poi/ss/formula/ptg/Ptg.java
src/java/org/apache/poi/ss/formula/ptg/RangePtg.java
src/java/org/apache/poi/ss/formula/ptg/Ref2DPtgBase.java
src/java/org/apache/poi/ss/formula/ptg/Ref3DPtg.java
src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java
src/java/org/apache/poi/ss/formula/ptg/RefErrorPtg.java
src/java/org/apache/poi/ss/formula/ptg/RefNPtg.java
src/java/org/apache/poi/ss/formula/ptg/RefPtg.java
src/java/org/apache/poi/ss/formula/ptg/RefPtgBase.java
src/java/org/apache/poi/ss/formula/ptg/ScalarConstantPtg.java
src/java/org/apache/poi/ss/formula/ptg/StringPtg.java
src/java/org/apache/poi/ss/formula/ptg/SubtractPtg.java
src/java/org/apache/poi/ss/formula/ptg/TblPtg.java
src/java/org/apache/poi/ss/formula/ptg/UnaryMinusPtg.java
src/java/org/apache/poi/ss/formula/ptg/UnaryPlusPtg.java
src/java/org/apache/poi/ss/formula/ptg/UnionPtg.java
src/java/org/apache/poi/ss/formula/ptg/UnknownPtg.java
src/java/org/apache/poi/ss/formula/ptg/ValueOperatorPtg.java
src/java/org/apache/poi/ss/util/CellRangeAddress.java
src/java/org/apache/poi/ss/util/CellRangeAddressBase.java
src/java/org/apache/poi/ss/util/SSCellRange.java
src/java/org/apache/poi/util/IntMapper.java
src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java
src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java
src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java
src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java
src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfPenStyle.java
src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusPen.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/BitMaskTextProp.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/CharFlagsTextProp.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/FontAlignmentProp.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/HSLFTabStop.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/HSLFTabStopPropCollection.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/ParagraphFlagsTextProp.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextAlignmentProp.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextProp.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/WrapFlagsTextProp.java
src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java
src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPenStyle.java
src/testcases/org/apache/poi/hssf/record/TestAutoFilterInfoRecord.java
src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
src/testcases/org/apache/poi/hssf/record/TestFtCblsSubRecord.java
src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java
src/testcases/org/apache/poi/hssf/record/TestMergeCellsRecord.java
src/testcases/org/apache/poi/hssf/record/TestNoteRecord.java
src/testcases/org/apache/poi/hssf/record/TestNoteStructureSubRecord.java
src/testcases/org/apache/poi/hssf/record/TestSSTRecordSizeCalculator.java
src/testcases/org/apache/poi/hssf/record/TestTextObjectRecord.java
src/testcases/org/apache/poi/hssf/record/common/TestUnicodeString.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java
src/testcases/org/apache/poi/ss/formula/ptg/TestAbstractFunctionPtg.java

index 1d5904613e6cb5d813484cc2df02875712629fa4..2374c9e6d40aa60235ada5f06cae5ed20b58d2f2 100644 (file)
@@ -65,26 +65,26 @@ import org.junit.runners.Parameterized.Parameters;
 
 /**
  *  This is an integration test which performs various actions on all stored test-files and tries
- *  to reveal problems which are introduced, but not covered (yet) by unit tests. 
- * 
- *  This test looks for any file under the test-data directory and tries to do some useful 
+ *  to reveal problems which are introduced, but not covered (yet) by unit tests.
+ *
+ *  This test looks for any file under the test-data directory and tries to do some useful
  *  processing with it based on it's type.
- * 
+ *
  *  The test is implemented as a junit {@link Parameterized} test, which leads
- *  to one test-method call for each file (currently around 950 files are handled). 
- * 
- *  There is a a mapping of extension to implementations of the interface 
- *  {@link FileHandler} which defines how the file is loaded and which actions are 
- *  tried with the file. 
- *  
+ *  to one test-method call for each file (currently around 950 files are handled).
+ *
+ *  There is a a mapping of extension to implementations of the interface
+ *  {@link FileHandler} which defines how the file is loaded and which actions are
+ *  tried with the file.
+ *
  *  The test can be expanded by adding more actions to the FileHandlers, this automatically
  *  applies the action to any such file in our test-data repository.
- *  
+ *
  *  There is also a list of files that should actually fail.
- *    
- *  Note: It is also a test-failure if a file that is expected to fail now actually works, 
- *  i.e. if a bug was fixed in POI itself, the file should be removed from the expected-failures 
- *  here as well! This is to ensure that files that should not work really do not work, e.g.  
+ *
+ *  Note: It is also a test-failure if a file that is expected to fail now actually works,
+ *  i.e. if a bug was fixed in POI itself, the file should be removed from the expected-failures
+ *  here as well! This is to ensure that files that should not work really do not work, e.g.
  *  that we do not remove expected sanity checks.
  */
 @RunWith(Parameterized.class)
@@ -96,7 +96,7 @@ public class TestAllFiles {
 
     private static final Map<String,String> FILE_PASSWORD;
 
-    
+
     // map file extensions to the actual mappers
     public static final Map<String, FileHandler> HANDLERS = new HashMap<>();
 
@@ -136,7 +136,7 @@ public class TestAllFiles {
 
         // Visio - binary
         HANDLERS.put(".vsd", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HDGFFileHandler());
-        
+
         // Visio - ooxml
         HANDLERS.put(".vsdm", new XDGFFileHandler());
         HANDLERS.put(".vsdx", new XDGFFileHandler());
@@ -238,7 +238,7 @@ public class TestAllFiles {
         passmap.put("poifs/protected_agile.docx", Decryptor.DEFAULT_PASSWORD);
         passmap.put("poifs/60320-protected.xlsx", "Test001!!");
         passmap.put("poifs/protected_sha512.xlsx", "this is a test");
-        
+
         FILE_PASSWORD = Collections.unmodifiableMap(passmap);
     }
 
@@ -326,7 +326,7 @@ public class TestAllFiles {
         "spreadsheet/testEXCEL_95.xls",
         "spreadsheet/59074.xls",
         "spreadsheet/60284.xls",
-        
+
         // OOXML Strict is not yet supported, see bug #57699
         "spreadsheet/SampleSS.strict.xlsx",
         "spreadsheet/SimpleStrict.xlsx",
@@ -342,7 +342,7 @@ public class TestAllFiles {
 
         // sheet cloning errors
         "spreadsheet/56450.xls",
-        "spreadsheet/OddStyleRecord.xls",
+        // "spreadsheet/OddStyleRecord.xls",
 
         // msg files with non-standard encodings
         "hsmf/ASCII_CP1251_LCID1049.msg",
@@ -377,7 +377,7 @@ public class TestAllFiles {
             }
             FileHandler handler = HANDLERS.get(getExtension(file));
             files.add(new Object[] { file, handler });
-            
+
             // for some file-types also run OPCFileHandler
             if(handler instanceof XSSFFileHandler ||
                 handler instanceof XWPFFileHandler ||
@@ -385,7 +385,7 @@ public class TestAllFiles {
                 handler instanceof XDGFFileHandler) {
                 files.add(new Object[] { file, new OPCFileHandler() });
             }
-            
+
             if (handler instanceof HSSFFileHandler ||
                 handler instanceof HSLFFileHandler ||
                 handler instanceof HWPFFileHandler ||
@@ -410,7 +410,7 @@ public class TestAllFiles {
         String pass = TestAllFiles.FILE_PASSWORD.get(file);
         Biff8EncryptionKey.setCurrentUserPassword(pass);
     }
-    
+
     @Test
     public void testAllFiles() throws Exception {
         if(handler == null) {
@@ -426,7 +426,7 @@ public class TestAllFiles {
                     file.endsWith(".xlsb") || file.endsWith(".pptx")) &&
                 handler instanceof OPCFileHandler;
         boolean ignoreHPSF = (handler instanceof HPSFFileHandler);
-        
+
         try {
             try (InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64 * 1024)) {
                 handler.handleFile(stream, file);
@@ -436,7 +436,7 @@ public class TestAllFiles {
 
             handler.handleExtracting(inputFile);
 
-            assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!", 
+            assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!",
                 EXPECTED_FAILURES.contains(file) && !ignoredOPC && !ignoreHPSF);
         } catch (OldFileFormatException e) {
             // for old word files we should still support extracting text
index 7367757f48982f8b749bba90f9c0cae92f1a20bb..740068fd9e37a947b690f7da5a81fba333e8c1ee 100644 (file)
@@ -28,14 +28,14 @@ import org.apache.poi.hssf.record.Record;
 import org.junit.Test;
 
 /**
- * Needs to be implemented in this package to have access to 
+ * Needs to be implemented in this package to have access to
  * HSSFWorkbook.getWorkbook()
  */
 public class RecordsStresser {
     public static void handleWorkbook(HSSFWorkbook wb) {
         List<Record> records = wb.getWorkbook().getRecords();
         for(Record record : records) {
-            // some Records do not implement clone ?! 
+            // some Records do not implement clone ?!
             // equals instead of instanceof is on purpose here to only skip exactly this class and not any derived ones
 //            if(record.getClass().equals(InterfaceHdrRecord.class) ||
 //                    record.getClass().equals(MMSRecord.class) ||
@@ -46,18 +46,16 @@ public class RecordsStresser {
 //                continue;
 //            }
             try {
-                Record newRecord = (Record) record.clone();
-                
-                assertEquals("Expecting the same class back from clone(), but had Record of type " + record.getClass() + " and got back a " + newRecord.getClass() + " from clone()", 
-                        record.getClass(), newRecord.getClass()); 
-                
+                Record newRecord = record.copy();
+
+                assertEquals("Expecting the same class back from clone(), but had Record of type " + record.getClass() + " and got back a " + newRecord.getClass() + " from clone()",
+                        record.getClass(), newRecord.getClass());
+
                 byte[] origBytes = record.serialize();
                 byte[] newBytes = newRecord.serialize();
-                
-                assertArrayEquals("Record of type " + record.getClass() + " should return the same byte array via the clone() method, but did return a different array", 
+
+                assertArrayEquals("Record of type " + record.getClass() + " should return the same byte array via the clone() method, but did return a different array",
                         origBytes, newBytes);
-            } catch (CloneNotSupportedException e) {
-                throw new RuntimeException(e);
             } catch (RuntimeException e) {
                 // some Records do not implement clone, ignore those for now
                 assertTrue(e.getMessage().contains("needs to define a clone method"));
diff --git a/src/java/org/apache/poi/common/Duplicatable.java b/src/java/org/apache/poi/common/Duplicatable.java
new file mode 100644 (file)
index 0000000..0c2cb14
--- /dev/null
@@ -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();
+}
index 9b5d6409e5f01d25539eb67b62afa403ed3fdb5b..1563363f10396f2a7fa9ac76cd1a3cebb283f8f6 100644 (file)
@@ -171,7 +171,4 @@ public abstract class AbstractEscherOptRecord extends EscherRecord {
             "properties", this::getEscherProperties
         );
     }
-
-    @Override
-    public abstract AbstractEscherOptRecord copy();
 }
index 8cb07c37e25947eda85e7937f011714a9312b278..0f192937bfe0adac108fa7d28d37349167dc75e4 100644 (file)
@@ -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>
      */
index 3877d11e36e205c934a2be1543823a293b8991a2..cb1b1fea4b79797131304c12addf889e991f77c1 100644 (file)
@@ -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
index 5f82aff73890cf8eaabf9ce078471d5cc36f27e4..b42a669977f93bf9301f37a153587cca0a098519 100644 (file)
@@ -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;
index 55d8e41667ce558c91cf581cc7524cd72d70001d..9e0236e7d15935d5350c616803b02c24c9de8797 100644 (file)
@@ -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;
index ce52b96d6a300fbf233bcdeb1c27d92e461d1e33..02ef1f94e4c2e0c27f5e9fe9ffe99dabc016220a 100644 (file)
@@ -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;
        }
index bd4afe89003696bcace204200f5c08ea5a566a8c..afd1fa8b4d53806b2d84f7309c84b5253a82fb0a 100644 (file)
@@ -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;
+       }
 }
index 393e21f387a06ad57be9c5e6b0e56a8a257ade28..2535818dfad4a0f30a1646650fb3f545d62fea0f 100644 (file)
@@ -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;
+       }
 }
index 4c128bd004e36c0760d03cc376c18ff1f0959a91..9d7eeddf3413eeb2657cd1140173c1d11aea404b 100644 (file)
@@ -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;
+       }
 }
index 1b2531aee7a3f9b109df1e104e7d4a2f5b07fd6e..ea1addabdb90500bc53b2f8adb68a0c46b833a2f 100644 (file)
@@ -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);
     }
index 23c2d3d61cd5516d68a91bc1780129a519635ba9..7e1f82d380f9d8c00f1bf95812abbe8072665b17 100644 (file)
@@ -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
@@ -70,6 +70,13 @@ public final class RecordStream {
                return _list.get(_nextIndex).getClass();
        }
 
+       /**
+        * @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
         */
index b403a0799be8121f07a6c3daabb1cb95cf6a2317..3bcc18430ed469ec2fe5256f4a95bf715cc2a5bf 100644 (file)
@@ -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 )
index 96830cdbcedcd98ef6ecf00895d73433f78b9c32..fb52ecf361af295357bab3d6363a046fefc63538 100644 (file)
 
 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);
     }
 }
index ae0005bd67f9eef976fa9c68ea47a80470b302f3..ccb2d17bae363dde9abbaa424b0ad400c42e6993 100644 (file)
 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
index 992ee87220bb7cf820617869b9032ad4a153ec12..beb8ab4ff6a7ed842772c7a915bbe1c16f47ee53 100644 (file)
@@ -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);
     }
 }
index 509d8d8dbfaa4e34fb09342115c0dbbc761d6c83..5882113cb66b1b5d05dc445a70db2e24be808b3d 100644 (file)
    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);
+    }
 }
index 007dd8652402ba18d6b79bff3351c95e86bf637a..68e75b40c94034ec1d952ceca682b7795bf9427d 100644 (file)
@@ -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);
     }
 }
index d40214523d40d6ad3f9048d0ddaf527c2db6115c..98c1e3e5dc9d35901494cf4ce06558beac469866 100644 (file)
    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);
+    }
 }
index b733f2f1fff352cbb8368575291f3ec8909b0226..8dd944e1155605e2a82574802db5cc7017d73e51 100644 (file)
@@ -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);
        }
 }
index 36533dab16652f0aec2aa75357af544a6eafb89e..ff2328eab39296ce777317f764d68aef5f751e33 100644 (file)
@@ -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
index 33114f1a739770f0f10afbb0d538fa6956d407c1..72131e010fd4d7a8dccfbd2a383f97e2a0e6bbc7 100644 (file)
@@ -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);
+       }
 }
index 241faf13951731683563787c73cea229c89ae0b5..21b423632f669fffdde6599b89374e5b5b3552fe 100644 (file)
@@ -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);
     }
 }
index f4c1fbe87f04858a54e2459181d34b36739ce155..46b4c155a9626c1e243b6edbeae58d784d67c716 100644 (file)
@@ -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();
 }
index c3c6851fe69402dcb3905145f3812799b1271f68..1b764977b0493ea313d539b6084b6780e3f53a0c 100644 (file)
 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);
     }
 }
index 52bcf2ad24819e8d202664b317e9a469e767266b..abfb2771060ce79373cd770afad6614804d3e039 100644 (file)
@@ -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();
     }
index aae5073d7596b5c2ce47977278d294fea198c636..da1fc8ba9a0c5e22b71470e8698300019f7553c6 100644 (file)
@@ -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();
 }
index 77e6e961816ac5bf91680f11b1857b2948b1818c..b5bd489f234009dc785835d120d4bb79b0915ea2 100644 (file)
@@ -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);
     }
 }
index 6037360768d8570422eca8fa1c00788eb8a22274..4153f8d58dde6b7d3942aa0deaf3661e01bd0c0b 100644 (file)
@@ -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);
+       }
 }
index eddd3425a919aa5a8ce79833751b97c3bfe9b64e..c8086c7ba54a0961b9755261dfebceae0b935b6a 100644 (file)
@@ -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);
+       }
 }
index f03791d071aa9e3ab16dd928e10fdfacc9bcd187..94530bea12c5fc2d2ec42984b282fb4ee248b997 100644 (file)
    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);
     }
 }
index 6ffb84b0ff5608ed6089c838b275caf6e247de34..aad2ffa9fb9bd45b9391f48b44e681baa9401dd4 100644 (file)
    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);
     }
 }
index 5ae7abebeaa6f99ce6c00f40ee62cb12fc8aaebf..fd9c4d4d6acdd2e783d8fe96c701fd59787d623f 100644 (file)
@@ -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();
 }
index 11d074817a5321ebe1c08984f3d64e8cf421118b..adc831af231bf52a5238b2b6e2c3b011527304ed 100644 (file)
@@ -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);
+    }
 }
index 1f48458fde097f13efa6c59e041a11011fcbc757..4adbcd69be88ffc476e404a167f925ce1e889aad 100644 (file)
 
 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);
     }
 }
index 6e0b86155fba97c322a5634b77b9632e97825c84..5416b7e9226fc6633488d8d1981674c52da3a603 100644 (file)
@@ -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)
index 0dedc62a63aaa5653e1e181d518cc7012f14c8e0..09080b7f41870c4df3f686dd9d92bb4f1cf4c41f 100644 (file)
@@ -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);
     }
 }
index 47020dab1ef08a9d4cc0c08442bb726296a34ff8..d367d460c37a94207de9b78936326e0bbfbbe688 100644 (file)
    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);
+    }
 }
index 55db860bb8cb46129f8c8dc7cb29a5720b1eecbf..099466a7e137d2abc9e2986a9dfe37b3cab3ea8a 100644 (file)
@@ -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;
     }
index f23f7317e60ffa17f25111be430863be6afb8b7d..0401fe549befcfa838710b9856b751e7da01cebe 100644 (file)
  */
 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;
     }
 }
index 8dbb534254d350f9d56f763aa2bb70f5cd602e71..99101dacb277b2800a87e08d7cc25bef456945eb 100644 (file)
@@ -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);
+    }
 }
index f74dedbfeaa220934ca669dacbc68b71f7189f73..0be6512a174101fcf2468e9a89ca58f00b05b8d5 100644 (file)
 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);
     }
 }
index 4025794d2ce1101da83048dbc5c8b14fa9f7c494..9adcc02cbe5822b2f66bee3d17cc279416d0cc7a 100644 (file)
@@ -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);
        }
 }
index 6eb2e82a6e7fd8adcd929c5ecaeabb3214de25f7..29338e3145bf6bb36748c169a6b8be47d1be8ce8 100644 (file)
    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);
+    }
 }
index e4c416f07bc271fa3ac850ee4abb6171495ad924..31873ed316a7bbe08ea8916b9e8411f0440b9460 100644 (file)
 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);
     }
 }
index 7ba2c64061d3357fe18bb3d2fc147c77db68967a..9132ca7e444038d6ee575b09063bd8f6c45f1e6c 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
 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);
     }
 }
index aa3400dde569e1f037393ddf3a4d06494af63a73..d7dd0d508bcc1ad087b8a3a66cb03ef87c168398 100644 (file)
 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;
     }
index 280e3e18251247491526be382702830a5389b6c8..cd577f465f5c7b94bb9c76aa98beedda60314efa 100644 (file)
    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);
     }
 }
index 2304c047051f9aa8cbf2d3c7e753ef5949be73be..61c4596c0208576c529e6ab5e20a3087fe05b077 100644 (file)
 
 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);
+    }
 }
index a0eb3f233f7ba06b9fbc95e5e47519e3297bbb2f..913bf33da04b182a8ff702301a5e1187a54c5124 100644 (file)
 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
index bbbe0b3eef44f9457b56a4fc2a589ff896e11607..905c96aaa4dee9f8dd314761ee818585b040204a 100644 (file)
@@ -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);
+    }
 }
index 20bba6bc1556ab3484256cc22d0a911edae229ee..7a4b103331826bfd54cd78f5d8c4c7412466de63 100644 (file)
@@ -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;
        }
index 9d3d6d344f4667ad42ce9185749bf66ebfbdac4f..10c0d8d2a6b1e36e325719c4954a6a8e7e0da73c 100644 (file)
 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;
     }
 }
index 43d764139a41d8e2ef5cdcfd9085f25d49346bd0..8c2226becc411f6fc99721b9af76da5dacc28fda 100644 (file)
@@ -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;
        }
index 4999fba6b2e27ec8a107415336026ad0e82f619c..9707c3d489a68df3e8ea22d4ec09a02e18e81112 100644 (file)
    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();
     }
 }
index 0eb886c2cc5f9e91688cda58352011d0c25f5be3..309057cae1e359404393338656e50baffe8f81af 100644 (file)
@@ -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);
+    }
 }
index b56d4ca1a0686c61fbf71bd4ce54b2cf94895574..3214fd64b148825f333bc919aeed09a907e7aa24 100644 (file)
 
 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);
+    }
 }
index e18754030040e0a6c0e5fbef0cf19489493d0db3..5c9b0f16630e55682533b39b1513191378bc1806 100644 (file)
@@ -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);
+    }
 }
index 5c4e96b70f54e70fb93339622ba9a6b3e89e83de..ac69fcf268ac09d3c55f899f4ce444a3a2e46205 100644 (file)
@@ -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);
+       }
 }
index ab76a43d83db04dfa69a907d331b5815dfb80bcf..a9a27c1e14a249ce2465832b9ab0699a974a3620 100644 (file)
@@ -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);
+       }
 }
index 1acb3f05aa78b21b9d9f338322bbd03dab213bfe..4d60a85fc00e0421e5d18166526083742cfd2e9a 100644 (file)
@@ -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);
     }
 
-    
+
 }
index 37bb5b1f8f99f590a4dcd77e08a11e5c27eab24d..673ee93bb493008ffaf801d162cddea93743aa9b 100644 (file)
@@ -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);
+    }
 }
index 848944732523ef39e551a42e5b3f30ce291ab79b..78a3428e9340392c1a787ec59312a54da06c5ebd 100644 (file)
@@ -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);
        }
 
index bf1825730df60dc9294bc405e2f843454bf37314..2eb447531d0273eed66a9b37fd89c5a522210e0b 100644 (file)
 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);
     }
 }
index 4258df5e1f37d69bee3fc9ad26d19043fc916958..cdae7efe85c2e23ed14dbca459bb66500d6923ec 100644 (file)
    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);
+    }
 }
index cf673397d6f2a61fa75d882424699e422664ff29..2a3cc2f29f1beadf42e2445894059cd483557bce 100644 (file)
@@ -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);
+       }
 }
index 08ba4f2f1329a50ee68dd0cf82db6bbe2f7146c2..1c5fa0c825e43945584835bcfd641a644a742e67 100644 (file)
 
 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);
        }
 }
index 87410618c24ca996bd0ff2d11f798b1715e8ecb2..fc9badf9f065a7e4d8ea67b72fa261efdbfcd8f7 100644 (file)
@@ -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);
     }
 
index 662be0c630816c69f22fdd41e8a4effe87862aec..86a382a3fb4ff198ab8a272a190a8dd2975ba03c 100644 (file)
 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 (file)
index 0000000..65cf121
--- /dev/null
@@ -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();
+    }
+}
index 50eb7bf95a89a6c001d73e8bb6bdf0982010cb01..2541636a9d79e9bf1705ebf8c93c3d14fd28719a 100644 (file)
@@ -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
index e2fd02ad7e5d4672e6dc7a2c7e6d67fdfed71e28..099dae67e8a0f005a8258193f3da2d8d0eebc040 100644 (file)
@@ -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() {
index 221514598886168e3aaef073e2e217b6d26eb736..6e5845b5cdb952a48d2d3ecc64502791827f9bd4 100644 (file)
@@ -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() {
index 570ebe2867ef40cb4afc24768661ac6915018fda..290a8c6a75acce46d94ea20238946de29fc32f2b 100644 (file)
 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);
     }
 }
index 62364bc031ffa871390bcc33d7a336e6fa09da3f..310324f75662eb4855a9f700db25af51e0215822 100644 (file)
@@ -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);
     }
 }
index 6f302729dbea632a7639292d7dbec0409adb7afd..9f839df36de7deb3eff212cb30e313617c2fd119 100644 (file)
    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);
     }
 }
index d050823a6fae11a92de80e9968d03ae56ed93430..f9bd30f881a5fef820326c72932c86c09f0da23e 100644 (file)
 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);
     }
 }
index d0e23c73b038149075d6e2ac93bb30347affb472..2d31ec6caaa9f92d395307ac937aefc2c7b673c1 100644 (file)
@@ -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();
 }
index 92966385e18467dec479054bf43b37b9f9edcd0c..448ae11a06f0f41a499dad56948f95e7fba320d3 100644 (file)
 
 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);
+    }
+
+
 }
index 11fd873ed6cc5a8ece2f3aa1e8a21cb2060633d6..a62f7d807dc6d95784ffaee7956cb7cca961bfec 100644 (file)
 
 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);
        }
 }
index eedcf46051717728f4cd731720fe85ee0a42bc0f..a411cdb1207088c882ec5c22078b01cc3050161a 100644 (file)
    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);
+    }
 }
index ff034ef556bef032bd50127a1083bff97ee60d63..bb37565c91695e4572c60a646fa2cf813e8572bd 100644 (file)
 
 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);
        }
 }
index e7098423e35861b06ac69701bb5f08b21e6ed14e..ae6ae086a7887c5321ecc12d2d79327e078550e1 100644 (file)
@@ -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);
     }
 }
index 0e8997dc19ce9b63c862878a23887ea742c8e350..955232d44edb0e9f67e4b808f2e03952f0b2ffe7 100644 (file)
@@ -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);
     }
 }
index 1ac28a4b7d6e9ab0bdc00a0b0ffc41b3b2d41c52..472f7d76dfa1529136c66f418f11aca6af46208f 100644 (file)
@@ -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;
+    }
 }
index eda3cd1f0ccc4af391e14113f47ff7ab7d26e4cf..42b2ae3a588bdd945da60112e5c0dd726d02027c 100644 (file)
@@ -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);
+    }
 }
index ca018c3e781aa085806277e99f485ff0467c7428..3636175aa2efb640bfb8f86bb7fe5fb22aa4e7af 100644 (file)
@@ -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);
     }
 }
index 42fb7be8295ca984bf7c268cc0dd55a5af1a8d48..b87a5fcc675a460a0c87ebc3b1270a0ee3568e86 100644 (file)
@@ -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);
     }
 }
index 80bd99cfc1a3a0327b8dfda26125121ae1a29998..00ca0231b25b625dcef05b5a708211b87b1aed85 100644 (file)
@@ -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);
     }
 }
index 1f564677bb75efbcbea9c78713f5f11121f6ae45..e2f7e045a8630167560f796a56e8d980acc25e45 100644 (file)
 ==================================================================== */
 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);
+        }
     }
 }
index a2c00b07d6b7adf0dc0ba20c8972759dbc4ea0bc..a3ce5754bf4fdccc6eae5977ad479bec8e850ff2 100644 (file)
 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
index e016ef45816f93790a0e9e9633bf1801b2683837..a6356ac2c5f766fb0485ebbaa977b2c92b6d5a12 100644 (file)
    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);
+    }
 }
index c71cbb2b66ca310c9b2cf0f406cabc251851969a..1b71f9aa99c0ba610e152a6841061d444a12bc83 100644 (file)
 
 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);
     }
 }
index de5f1e11416c4aad2761083f21c38733288634b7..1c05a02e9a3c67a01bd27ff40ccfb0b0d7038a12 100644 (file)
 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;
        }
index 30aa1e2a2807cc993e0a23780a9a4d63c8db7288..9e3e144532d663890c22bdb1296f112b63388a23 100644 (file)
@@ -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;
+       }
 }
index 270440f6656a6158e7ebd0b36c5ebf9f29771eb0..d9e56affb6c1e9a2c82897d6c8397bcfc2e8b252 100644 (file)
 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);
+    }
 }
index 9278ce607bc033562228a4150fb3e7b7fc0ab011..4be445956c51e726f6bb96cd003fe06b11bf7ffd 100644 (file)
@@ -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);
+       }
 }
index 39992bbdbc286d733071884309ebd54f09a3ed94..4352978141b5ff5aed17b9c6ab1c3134cc63ccc6 100644 (file)
 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);
        }
 }
index e226b344d00aa12f871f866f25847de4103d494a..46a8f5106c1b70a252d103aa1c34227e81affc26 100644 (file)
@@ -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);
     }
 
 }
index 9d3dfd0c416af4eb803a5aee4db7dddde79dd364..a9defdc2515e536976c11743d6415426b6a8e4b8 100644 (file)
@@ -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);
     }
 }
index 2e3b49d339916cf923460a8f4c14edf121689323..c76e92848aab9edfbb2fc9a51c62fc9f4c577ed6 100644 (file)
@@ -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);
     }
 }
index deda2f39a4e5a33e13c50534b282546d825f20b6..451ca35dff808e82c8d3b091365403ccceac4c6d 100644 (file)
    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);
     }
 }
index 365059f47aa22bd45941c285d26aa6f26f23adc5..f6b29146065ffba895ea1904ba274a2a5f4ac3a2 100644 (file)
@@ -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
      *
index 447291daa3bd00b0a33a2cb1a6cfa8ddf5679de4..6dd80e911e617124484a94566c1ae87b56ba42ec 100644 (file)
@@ -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");
     }
index 195d9319cf8de33f5928e65f055366fb2c4af80d..0672faa054123e675f76b0f51e6449e62a79e5bc 100644 (file)
@@ -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;
index 2d611929f746b2fc3fde42a1fc5d96e9a79147a9..87140b7fc9f15c662b0c80a9f16f83309aeaccf1 100644 (file)
@@ -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) {
index a1d86247dccc7f825075989eb4b49d14eb5014a1..4b2c216a709338df56b66c98ad80bc3abdec1206 100644 (file)
@@ -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();
 }
index 72b5639581b6c524c975a09c30259baac797b22c..222be3060f5e98e6505474c711d8abf28f70bbc0 100644 (file)
@@ -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 &gt;= 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);
index 4b0610aba72e8b1333d95dcd813a0172f810e869..c50e01b00255eeed5a7b98e7c3d74313ef049ebc 100644 (file)
@@ -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
index 211ddcbe58cd07bb1880b031d4f4d3318551ab00..c177949b3e47030fc5c26876a727ac6f27da4659 100644 (file)
@@ -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);
     }
 }
index ed8f4ff970cffaae87a43651ea7b77951ba47213..997b721e83a69960df895f625eee56ff0e6956ea 100644 (file)
@@ -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);
+    }
 }
index 74bf8cf916b42fe03f943de3614399cd665fb289..13d0c0a41f1592582935420a0d80b7170bbbab5b 100644 (file)
@@ -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);
+    }
 }
index 2563f3432689895a1939a1b8c2870947e38f1f65..2e84590aa2fa02710ed22cabfc4d21d24235887f 100644 (file)
 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);
     }
 }
index 607c4a8b7c98fafe5965a42017522c48094ced54..4ab1568351aab8a68db378dc71c3d6a0531b39ac 100644 (file)
 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);
     }
 }
index 6ab28c2369ef0458ee7749bfbc8811e8b06eea8b..7868185f0d5f3e40cdaa1dde263358e4581cd157 100644 (file)
 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);
     }
 }
index 9058026ad9966d7636f8a842b7fced74d48a7605..867c15c398c5faa20b7a01173816a52285b72230 100644 (file)
@@ -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);
     }
 }
index ba51b6df38da8b148cf23fb5fc47ed9ad12298db..0b6ab783b14b539fa0f06a51a40b925aad8019e4 100644 (file)
@@ -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);
+    }
 }
index 3aac08d69fd3d28ed880ebecfcd95b8feb5dcd7a..b8846e127d7dcecd7f21c28a9419d8423ba6c5c8 100644 (file)
@@ -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);
     }
 }
index 933c5a96983ab2a8738cc25b5f5ebbdddb9c2772..c86622077f05e60bec09960ee8fab498cfab4704 100644 (file)
@@ -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);
+    }
 }
index 60ba7cd5df2935ca6b5349aaaaf62a87df7b0767..86c4f7c03e11b46c4d8dc5e9107f150b82453660 100644 (file)
@@ -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();
 }
index d19d2718d1d4e0f843ab472180ceacd2ae16c816..40907ec7e79617660a0b700edf3a283bdf73d957 100644 (file)
@@ -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();
index 400553721e21c2db18ee0e4f026ffafcda3dea81..a8af77c2e187690d5b0c09653ea1efc92daef19f 100644 (file)
@@ -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
index 987da8f768f8ff87496cdcbee493ac36a9e2080f..5ad1635e9bdb6d264a70e99c0053c704dced452e 100644 (file)
    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();
     }
 }
index ebe1c7ea3e1edb1a8e054a86ac52d91e3712d3c5..26c121401ab920132dc4b2560f93d87299f48f4f 100644 (file)
@@ -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);
     }
 }
index 4a8f1b33f2eaf1fc11d0c889d668e4d96c295657..87458f5d8e6680ef6ee5f5af3aeb54bb71461c93 100644 (file)
 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
index 2987e042ed5df751b3397428375210ec41651ad4..c04776d849df28eaa55fe61b9b1136cdf5442ca5 100644 (file)
@@ -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);
     }
 }
index c4dbfb0a53c0c6726f62df83df4a5003c6977600..73757a4bce51e20f159b645dac5faae0bf6072cb 100644 (file)
@@ -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)
index f7f1365d0e620f588961d1621bd2f0198cc2a37c..aa79678f2c7c77dc5aea6f2ba938dde9e776bfb8 100644 (file)
@@ -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);
+    }
 }
index 05c66f78f0a5eda81f3c284783146e0fbd105b2b..8945d8035dce48386697cdb6ac2c4df0165cfc28 100644 (file)
 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);
     }
 }
index 20e10945c07065baefe0a70c6638216e741d9f73..400caf68a84647805891d47c9a6fb0419f49f290 100644 (file)
    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);
     }
 }
index 904fe041092511879f21a2543243f31d062b6b85..08d14bae0c4e9f6f4d4c15a37b806f2846ab978b 100644 (file)
 
 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);
     }
 }
index 328402db80a7e97dd5933780714a5a78b1b92cc8..a54ba8fbb4ecb8471953a25fd219e2ac7f216cbc 100644 (file)
 
 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);
index 51fe091808eb1176f094460eca8406e4253474de..3f23037d2add0c7066d52baa74e25032bb5b2832 100644 (file)
@@ -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) {
index 610c57b835816cf7b6f25665efcc49b336fb5ec9..ac7637672b94d6e424c953f98df17c5d5ccb3d6f 100644 (file)
@@ -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();
 }
index d672588614a0f5ba65c30cb342cb5b4d5283b7ad..106331bb1a010bf23477f6bf98af88fc91cfaa2b 100644 (file)
@@ -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);
     }
 }
index c5b7db75627d18cb6c58504ab9eb04a3c7a07183..8acb8d0d6df9c6fa45715e0c04ef74467f14fff7 100644 (file)
@@ -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);
+       }
 }
index 9e242135193b8d0447777aa7aa40311d95c96879..aaab95881f6c7a93bfd58ef29cd923c2a10fad33 100644 (file)
 
 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();
 }
index 32046669a60cff394746b0068f5fa184eb2c2fdc..212cc63360af4f2bfa4205fea38b1202dc1e15db 100644 (file)
@@ -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);
     }
 }
index 833357029eb9d0be5b6719864d66dfdc6531561b..f1bfd672b1c3c884fe097baad4dfad3a32c21005 100644 (file)
@@ -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);
+    }
 }
index 2dd1d0ee01efcbd6684824d6a365bf848448426c..571b58f59e932943176cdb992b92032731fbe6f6 100644 (file)
 
 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;
index df15ac2355d0286111697d682e904619b070c2fc..6a9ed63a54bdbde4e287b8164088e750eefba4bc 100644 (file)
@@ -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);
+       }
 }
index d5c9e3f425b700f76ad588ae309688076386a1cd..1116282ac8f2c932eb60d36c54cae81e066b0dd4 100644 (file)
@@ -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);
        }
 }
index 99d7d490214e07d2f3853ce1a2538ea37037dfcd..11cee8ad20c1575f8c76e80c33c8cce047e10aaa 100644 (file)
 
 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
index 9310766aacd6b331979193e81beb6a83202b2e7e..22e8ddb0a6a8f1342d52860da530ec006f4985c2 100644 (file)
@@ -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);
+       }
 }
index 9b4dc55c849ad2fa5899ef5621cfe89f1c8161b4..f71da5b0a3aa6c476fda7f06a083cbd5fa99ade5 100644 (file)
@@ -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;
     }
index c8d669130097acf16b69163338379eaa68d0684a..1095c7a0a33b7652886e976683ed0c0f2bea0602 100644 (file)
@@ -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);
     }
 }
index c32cffbb2b4ac1aa344652b3db0a332ef04a2c94..ccbb2b62618e3eca5d32cbc073bfeb43a76bebea 100644 (file)
@@ -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);
+    }
+
 }
index b3410ebc3e05ff2bbd7e91621e7fe73909c40578..09c8c3b40b0a9a89e68d3ed4a8d254455d3cd29f 100644 (file)
@@ -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);
+    }
 }
index 2439a9a42d5bec1aeee050b7b6a4292234d1ca79..601be847df359819c89367c7c0ad25aae3596c40 100644 (file)
 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);
     }
 }
index f15baf6ffb789e782f09ba975cf67f66c4a98d65..d8e8a9a45986852f3d35c7027ff7ef86c5166340 100644 (file)
 
 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);
        }
 }
index 5995eda6da809dfe960a5825754ca0dc452ddc75..27824f79b80291b188f5322e001c3cf593c23959 100644 (file)
@@ -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);
     }
 }
index 440348e37a228c31b4e068e086ba10c513f4fc30..8aa8f60933c048420b381a4c0da6e938254fd2eb 100644 (file)
@@ -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);
+    }
 }
index 12d471c3856434f06224693539db5ce9a34aacc9..c5b26235cedbf91f82d602288ee305719fcbe32d 100644 (file)
@@ -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);
     }
 }
index d58f2ee3eb9a8b178c4290e623e9a56059bbc3c5..d9aea08ccef181de6057c26cea63f16f5da9e957 100644 (file)
@@ -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);
     }
 }
index e6d62ca4ff8567e15800ac53e7399179a4b6983f..65773251c125d7de587088a74b8402c7ea9a7c46 100644 (file)
@@ -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);
+       }
 }
index edd49625691f20eba91af47d9ae85a84e28f5b83..41e3e2d988232fb13a425d85bce411684135fe46 100644 (file)
@@ -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();
+    }
 }
index 8c9e0be763c6556757dce2bae1889740062d50c2..87c5798df8ffee23ce34a48e5dcaf646d76a0200 100644 (file)
@@ -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);
index 5debe7361c8519d8b2e03e0c718b251c18e0266e..4b4332791867fbbd5bb721fe973eab8fa19f21fe 100644 (file)
 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();
+       }
 }
index 625cc9a6ac0be29454a19b0dd462b6e68b7fc032..2afbb3813dd0ffea24761686b3b897d45dab137d 100644 (file)
@@ -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) {
index 654abaf41fefaffbb021897bc03ac37743d0a3ac..e6ad8bb29d5e24a5911cbb214ab45876489f03a7 100644 (file)
@@ -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) {
index ff442f4e60b8908b565fa668c8d0a63f5a400059..62c3df3a05002e6dd946a64fb049114666144c7d 100644 (file)
@@ -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
index f85b3375a36a3e6461792528aa0212c434881790..c698cb0d275a57ea9abb4b846ca7babccf5e0568 100644 (file)
@@ -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;
 
index c56d114695258e5d249395695915d796d0649db5..8336dcaefe28f919c8a0d02687b951c2bbc264bc 100644 (file)
@@ -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 {
 
index dc238a96252e7fae80143161c64297155deaeb0b..21c9ad8436667e9467d100791ea717c879b6fb32 100644 (file)
@@ -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
      */
index b612a5ee3e16c7dfa685422be99162a428eb31b0..a87a24a81ba882e3e174e7b2c9a3f2642686ec4c 100644 (file)
 
 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) {
index ea781a8062925f1d192481825fed12108647436d..830d24fd73d0a2d1a8e9bdceccbebaa532d4f03d 100644 (file)
@@ -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);
         }
index e7bea75a5a9de11668356e9d484308c8ce80aa2e..9c41995dbd6e1cd466d64a331926992b14a20106 100644 (file)
 
 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) {
index 2e5cb7252bcbcb4079d864645c96d536a3204a0c..466fad4990b051382cdec4c26433734aaa0ecffb 100644 (file)
@@ -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();
     }
 
index 63c7f6b36350ed28033002b3ebacfd2e50bc4135..8d88a6ab234f9a499d2ada600c30ed7a909474f2 100644 (file)
 
 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);
     }
 }
index e6ea05de236034beff673c637b9086dbfdb92542..22a4aed29ea07bc708bfff269640a097f4e2ebc7 100644 (file)
@@ -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);
     }
 }
index b38829618011a2d944ce97d9dcff3896ccf409da..08d3ea04f6a9fdbcbe367716c844893ca50d1c1c 100644 (file)
@@ -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) {
index 03d95caf3394532030e70482254969dd3a115f96..a8c9e807cd0619a1565439d538d5aa2206a32f8e 100644 (file)
 
 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) {
index 1294e43d16624ada18b234cdfd7c75b57f6d2823..e03e652698eea2de055fa3a0f3df30728f2c7ec3 100644 (file)
 
 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) {
index 71df40b9c07417327a8bfcadedcb9f4b83715681..4ce6a1e107abb0109cdabe09d84ec083b50799ca 100644 (file)
@@ -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();
 }
index afda4669a6db5e352f896464a3b4c8034ad78a42..61b19fd5df348076b940b9125e75b94efbf0c1a5 100644 (file)
@@ -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);
+    }
 }
index 77746d40a19dec97d4b968fc4a66337c6cde120a..98431b7e187d6547afcf5f5df45c8c5ad14ea81a 100644 (file)
@@ -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);
+    }
 }
index 7996aa99c7a8c4dd35ba5e3ba29751548bd998a9..8ae0b7ffeafd7948cdf4b1ffd53a5dee9ebf7cdb 100644 (file)
@@ -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);
+    }
 }
index b08fdb29e67f400e7c2e0a514f6352d4c541cb24..158284f21cb5ca478a98ebb239d98510888083c5 100644 (file)
@@ -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);
+    }
 }
index 8eda4ba2d25ba47324658b689ca0a284bbd912ba..bb61c8d94008e68d56da9feea68c91289ffa6d64 100644 (file)
@@ -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);
+    }
 }
index e418119b193f675fd7fd564d0ce2ec860939a69e..75cb72e78ea1316c9c034ef7b1d0a3dc3b1626c5 100644 (file)
@@ -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);
+    }
 }
index 1c4f4eeb435b2219c1ad5bdd7d801207dbe7d637..df1c0482c6a3628a63a44702e129f619b2af5d84 100644 (file)
@@ -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);
+    }
 }
index 58c3af30e3b9f7cdd4d5626e86d442bda7687f95..2cc62b82715db2d09450b7ada031576132987a1f 100644 (file)
@@ -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);
+    }
 }
index e50db003673ea74c3ae0e09f88683ffdb5481399..128d621c8918b6775e0abf1d7ece9c87e8512af1 100644 (file)
@@ -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);
     }
 }
index 5404d8e371d529695db474bed8ac71f6fe702b07..f0264f4b7b68dd080c25c56985bc01d0432a7954 100644 (file)
@@ -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);
+       }
 }
index 79574286d854d30132c82160140d16ac73b61f36..60f45ae9bf4bf75f3dbd16dbf0e3f120781f5960 100644 (file)
@@ -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);
+    }
 }
index cbb092c4f806b6dec70add1bcbee75bc14cd111b..4e821b7af7b2af958cf568c90ae549e7834ce517 100644 (file)
@@ -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);
        }
 }
index e097ce0ad903e3646a54f942c432adfb123b9851..124e40519b5cdd03a71f7e975e39ba01169ff523 100644 (file)
@@ -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);
+       }
 }
index f3680f3bfbefb2971e9c258cea1ca99baa5c4b54..d5237d0bfd368aba426c508168f1b27b35943594 100644 (file)
@@ -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);
+       }
 }
index 5599f63697f0a106e586c4f2293064e770d95ef7..0d5fe118150d0352a89437acaeb3e8f673e60d6b 100644 (file)
@@ -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);
+    }
 }
index 33590ece506f2d3f1fdd9a2cc9c6572167d25476..ae17a05d96c4fcc3f4124b69593c47674ef44a09 100644 (file)
@@ -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.
index fb98a7cf82f91d532f5f83ff9efe95d16864af3d..7403706a767a7cfde5c431a8ba165af1cdaf1c69 100644 (file)
@@ -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);
        }
 }
index 5ddaecc117587eff07fa7361d85d8b3336f393e8..f7d82b3fdd07a66c30500cb5fb8981d705ce2824 100644 (file)
@@ -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);
+       }
 }
index 09229072da50b0aaebf123de3106ca8f590a56fc..49a2a8d4af9dc6da5368df79e79a00cdb74deea2 100644 (file)
@@ -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);
+       }
 }
index 4d7d29f3287d59f568a2fc76bc3649cbd3f3e232..25b80d3d00d5bc914a0cf024411b0dbaf894b5c3 100644 (file)
@@ -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.
index 2c7d5c23b213d1e930e40824f4b7cee007d957d9..072f9ef72f16eaebb0af801682f7591f2197c33c 100644 (file)
@@ -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.
index 64f29efc44b1496e268f0a14bc3962e9fb217269..acad498488c2cd0be5cf241e8ca3e955903c56c8 100644 (file)
@@ -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);
+       }
 }
index b26f39b1e24957745d83ca0e7214e5ef4342f390..545edc48419ec6753482b2a6323352f0b7751b5d 100644 (file)
@@ -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
index bb539c21d899cb27c9936382080a1dce45a4ec83..3651101eac074d4e346d8b2de916ee402d3a7859 100644 (file)
@@ -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();
     }
index 6b24869bfe09325db61c91f1694293cf99d8412e..2cbd5b03a88e92a25d3b70b042bdf3e054259f03 100644 (file)
@@ -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.
index cd3f08ffc21c7d88bd9a708eff2dc5c62327f48b..1d79da8ddf6e83c7a84e1c8ee16e6eb1387c2203 100644 (file)
@@ -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);
     }
 
 
index f78574a67480fe9eba9ecb825818a22c25dd2a82..1ced6abe94b7d0d1fea6b415c76354fed211c291 100644 (file)
@@ -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
      */
index 2a4a3ba98b53ecc14f72ac188010e1bdc3606ce6..17aa2fce882120db2617a3f1fb37e06b681391f6 100644 (file)
@@ -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
index e0acece3ba34203cdbdfd49de0bd28bb9dab2d5c..21eef9d26f98fe624ef51b6653757342597c85d2 100644 (file)
@@ -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
index 96c8501d3380c33b2e442bc33be63e4fb7e3403d..49d0afc7a069db9540e3124c732e96b5e0862926 100644 (file)
@@ -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}
      */
index 9ba2a27b1678d6e7e1dcb659711d964d1e18f317..2c04258800e06ed39bedca5b201b19c60a07e5da 100644 (file)
@@ -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.
index c179f2603f30a4eb2890b8565fdfa2d315cd585a..d52bfbe9376e18f9e55b0eb097bdca0da95ecfa6 100644 (file)
@@ -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
index 920fbc2e660d626c73714f31bbacd0420f6d157d..332808d7851aca457a86af40b784690ae4047b94 100644 (file)
@@ -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();
     }
 }
index d538a9b44fab9919dc92fd04b359c56cbe89a208..3af8916d1dd8be8117df81864cbc1f587a20c813 100644 (file)
@@ -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.
index 6d095149c5ab7aaae2431e485d67ffd8a51db484..e56ff395bec3cf87fd1cee39c7eed56f1444c65c 100644 (file)
@@ -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.
index 09d8c65b4f8fb2fd1fd556adbe7295669d8641f2..877bcc9480f919d05efa2ec5aaef4e5a5b5e97f9 100644 (file)
@@ -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.
index 66a49188a71ff4d399439f5888606fccaf19883c..f882371ff664604391da1c692f2c70b81c9ff15a 100644 (file)
@@ -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.
index 5457702ee633939a063edec1f924f5f6f6fb762f..70b83bed6dff7db6a18ff4eea71e61d55896aaf6 100644 (file)
@@ -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);
     }
 
     /**
index 6ebef9abd484f41898fe07982349adfaa9816fef..22405ecde26b24f437066ddc259b272613524a98 100644 (file)
@@ -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
index f6b0de4f29aba8bce07749867f6a9ca64eda1aeb..bf7f92af08fa1dfa1082fa43ce6a02a36c980379 100644 (file)
@@ -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);
        }
 
        /**
index 17e6134bcf4e00acd44f8cba2983ee86406c61e6..62f8fca5ae2286882d381749758e30cf2bedaefa 100644 (file)
@@ -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.
index cc79df93d7fc54ed92a43a7d91121535f516f802..ab29b181a53b97215b2f3b327c541bccec4401e0 100644 (file)
@@ -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
index ce447694cbae86ef7914a4aa50d5ea746e7139d1..f41673310fd3529431867a68974de0de459c61cd 100644 (file)
@@ -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()
index 9080a22e24cfba02b4bc988dc74de68fcd14dfc3..7b5b7763a8cf01ccfc13ea6726efe184fc3079c2 100644 (file)
@@ -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.
index c1823554f0241ee10e1e279a2ac579229f69c68a..a9dd25519a1e88247b30ba137b6b88e02b6ab847 100644 (file)
@@ -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.
index 73d810ea54646c2e22dda08d5f0798a469614e04..a7107869601fdb0c50809843872943b36e9f87e1 100644 (file)
@@ -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 (file)
index 0000000..efdb5b1
--- /dev/null
@@ -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;
+    }
+
+}
index 2d8ba002d0339d8be0e64dd535a97edbcd86120b..145b2e2085b4bba724e53081f834dcdc90ac0bcc 100644 (file)
 
 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;
     }
index e798337f82019da8dde1764088e09294990c5866..dde71cc51524bf2ad790b5c1d22e05089b62caaa 100644 (file)
@@ -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);
+       }
 }
index 2e6e94008ace5598b8f2153651b7e2d535c06f2a..9e9a45fb55e1bfc3e67d4c403bfed87c374bcbcc 100644 (file)
@@ -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);
+       }
 }
index c8e2b295420c10739199f5bdcdee0136699f94e1..2e8e08e16f1232c9ca98aa8d0253750beacfbe2c 100644 (file)
 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 (file)
index 0000000..4e927f1
--- /dev/null
@@ -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);
+    }
+}
index 5d08211c0ad16e96e8deaf856c3a9771e8b846ef..851e1e6c94bc33ba8b6a4f54d5339685ee775df4 100644 (file)
 
 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 (file)
index 0000000..0f33254
--- /dev/null
@@ -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);
+    }
+}
index 1ce8bce1f202e2eda80491f389e6f521c2a4ea22..63d3172ef6c5296a39c3cf1ad8ba1a18392bea00 100644 (file)
@@ -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();
 }
index 80689564b96d0d824a96c941570ea9d71237aa15..fedaf31b22ba891ffea97dd4e0873ed9e1127681 100644 (file)
 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);
     }
 }
index 8c170aa3afb4dab108a3b9873119ce72d8c39856..dceb7b86b14b3cdb6a17486d9646227df5dae060 100644 (file)
@@ -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
index d1045400824f24f5cc6517ff586a911724c31f93..a55fa6fd7b83a046fe8cac78e1a74ca5184a8943 100644 (file)
@@ -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);
+       }
 }
index 0a1bb11cd359e919d4fd06025835b1f23e7a0683..119c23b2dab4c775e78cf91eaf7c89ea3cd8d24c 100644 (file)
@@ -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);
+       }
 }
index 8d8a059cd4d6e1193e2fc5a142120913fe2cb733..ac615ed822f017307470945c5fdb8e6becf7a312 100644 (file)
@@ -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);
+       }
 }
index 70c82f0a33e507148f03eec3a21516ffa54a5d46..49202d4e8e2eb5af472733c81a7479f8a88e8085 100644 (file)
@@ -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);
+       }
 }
index afda2ac001f4b90ac94047a7f22a9366fa102577..0b1eb257d320fbf141b3d7afbfe50a50d93955f5 100644 (file)
@@ -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);
+       }
 }
index 8c761ea8ffd54352dda64e8b404ad2ff0ea72c82..7812902ba05ecc7fbf5b2bc57f862d588623bbb2 100644 (file)
@@ -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);
+       }
 }
index b4fb2815b9ce677cc13a78dff4a99b9405528587..88d11df8ba38afda91d48fb8cba4ef5bce29d55e 100644 (file)
@@ -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);
+       }
 }
index 68cbc96c9e4d3d4d1002e090e9f92bf531680d8f..14a97a2772f4cbbdc5cbf71b60f9fe3aa35a71e1 100644 (file)
@@ -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);
+    }
 }
index 0895fe94f14ebf116aaf3d2b6e826315159957aa..6aabcceeac62f58256244c96b599d00e01ac48f2 100644 (file)
@@ -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)
index 88b55d535779d5689ea45bfad1613b804f3d4dcd..7d3defe16d91a3baf7d411e761026cfc326c1477 100644 (file)
@@ -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();
index 3b8f83d8efcad8119ff1e549ecf9eb5451095dd4..dd146e03f34e3467fdbcd1a4da727eddfa7b58fb 100644 (file)
@@ -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.
      */
index 50a2ac2c13ec7de6bf8213125e2d3767a84704e0..c70e525667e0cc6f027c204bc37fcdc7a2ee7ddc 100644 (file)
@@ -53,6 +53,7 @@ public final class CellRangeAddress8Bit extends CellRangeAddressBase {
                out.writeByte(getLastColumn());
        }
 
+       @Override
        public CellRangeAddress8Bit copy() {
                return new CellRangeAddress8Bit(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn());
        }
index d7bb427cba4778e4f19d4729c5d24ab4d9705eff..5b084916a2479953263f52ad2f7cc95533f44031 100644 (file)
@@ -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.
      *
index ad75f5b134f7e136b9be29315ea087dfd453a859..d3743c47d4cc454abe85c42e272055b62ddd9dd6 100644 (file)
@@ -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() {
index 6518281d6f2da808320e3dc4147fcc99635243b9..38f666e15e4c6f8243b6bf647ae5f7cde705cc45 100644 (file)
@@ -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() {
index 826b57e41977cb65f8485b30c1c44776c4e417cb..81aca4e417ffe3562b3b561828d7894c6b159b42 100644 (file)
@@ -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
index 0f3e44b10b550b13d5e9fdcd29c5f3bba684993f..d45fb28c272273273b3c8c3a386e67c9fa93754f 100644 (file)
@@ -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() {
index 8c241be7803978469eb8effe38a547b23f05d1bb..93db9a279246b3563e68e682ad6c964132d8ab71 100644 (file)
@@ -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() {
index 176e779b31bb9235a395e7a5d55f2b695875d76e..368d2dbb3136e1e2d672ef53a9476e15444468e9 100644 (file)
@@ -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);
     }
 }
index 549d0f85f97ce2d3c228fe5c0e4fc1ed81045095..f9051b652c2d6fa9e11b62ad47d817d6a7c4074d 100644 (file)
@@ -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);
     }
-    
-    
 }
index 098a69452ac6e894c5cd6c4a0670a08b369e639a..689c06932dbe4c948a816be4d3e366df3f0559f8 100644 (file)
 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);
     }
 }
index 6c67f32015dd32159c97b30a639529df15d38ffb..c0482714219b8d26e4504c21116d5623bfe2701b 100644 (file)
@@ -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) {
         }
index 550dcde2ee7e793316b900aa3de2457df9bbd6d9..affadffdc29c7b5d4e2c17bb8c8a699eaccd1313 100644 (file)
@@ -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 {
index 2e838f7ddf64fa2a17ab506d1c55ab59f0532e7e..9c0af9b1775d5d079ec85ace4a9afb1ad915b65a 100644 (file)
@@ -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);
     }
 }
index 9c43626f2d39363249ca3c9eaff7d7770b48a219..c54b9851d0adf40c5f40b0c291977f18afcaf092 100644 (file)
@@ -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);
     }
 }
index 60b1be28418b0c858b613c7672108eafbd7177c5..652e7f51d731c3d9511c47ab6499cc93faf76df2 100644 (file)
@@ -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 {
index 9c7926033d9f3ce9396ccbf352191ad06628e2f3..9fedce6122c37f4b8b0d6630a766e618ffcd2de1 100644 (file)
@@ -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);
     }
 }
index 2c42c60f8e6091e113b4a6b10a5819696f41aa4b..139bb2ac70deb31cba02f55767a18a942af0af5e 100644 (file)
@@ -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);
     }
 }
index a60feae30a9dd23f87a9a0d6829af65c366a1356..4c5f2e0d3d89d81b31925ea5b1dbd5b7f3fcd93f 100644 (file)
@@ -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);
     }
 }
index 4c4ca2a3fb360cb7f4d00a6a3b18aeb8252272da..2dfbc1f547c8999ed56073341e85cab7f07b3a23 100644 (file)
@@ -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);
     }
 }
index 66664b9d4af03d7b7b44d566b37546efb748931a..d2cebca389c51097e5af352a5a88b7185eaeaba2 100644 (file)
@@ -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
index 873c1abde6acf6f2616998f83beb7432851fd7c9..4af028656a658a63b73a99e9e25df98b598f11ff 100644 (file)
@@ -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);
     }
 }
index d3a18e1398d37095c49a670b77bbcabe27635111..8d6482b31c8dfa7b0a70b65ccda6c3df8e08374a 100644 (file)
@@ -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
index 04cd5a8543c38e739453035f042e041512184e50..3b180b20d40b7cc4f0a1f1a1ce5526c11d045f7f 100644 (file)
@@ -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 {
index 50ae3d2aeab66e2d74c1b178882383a122688d3d..ae406f1488629f400d8d935a4a1e5508f2b74f59 100644 (file)
@@ -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;
index bfb7aeba6a54e6b5b9d873b1e0853f00e50d1430..d05637c3acc9d934dc0650da3735f85e32844221 100644 (file)
@@ -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 {
 
index b18bf3a3359cb617369ec6bae2081068fc84aab0..aedc6dd86fdeb196c9b76ec101e48214aea1a4c9 100644 (file)
 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;
+    }
 }
index b356591b73728cd8f76c6b92305ccb2bdba5e260..66ffdcc516acb1c518d7238ba520fe94e5345e4c 100644 (file)
@@ -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);
        }
index 823a1462feb5185d88214dffee596a94393373f9..0b43cef9dfcd78cebc1b8003591513425b3270ba 100644 (file)
@@ -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);
+       }
 }
index 9c7a5da0d55c40032fca52a3562c52575faffb5e..d746ee0bc900551bd35c650da942705c2faaab9a 100644 (file)
@@ -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);
+    }
 }
index 0685e8ec9d2cc25c1a7468adcd8aa80e553c6500..e2bb2fe66dd7560af4036fb9639ae2c9260972c3 100644 (file)
@@ -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
index bc8f76e3dbe81352c0dc8998fea6a41c1d3df5fd..0c0faca5052b0a1f3a53cd8df98aea04ac263e40 100644 (file)
@@ -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);
+       }
 }
index 93f9a06332be0935713f6015e41f81b806531176..ca711e6f06ad6829d817bfa668252d4199ba3329 100644 (file)
@@ -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);
+       }
 }
index 21c19ccd149319a5f95366c3636234f04a2109c8..bed2914a2a34f9136679ac301684e4b21846f4b8 100644 (file)
@@ -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() {
index 66072bdd3d2ac0f24d1a0bef5fe33010ab9e9bf6..7426c41f7ac63836ec5d11255d17a05062dfe6f9 100644 (file)
@@ -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);
        }
 }
index 0af61b897fa50e82111772aee8c6a9dedaeb2e1e..d046b684b68cda1864f8e35a5853ecf9ddc4270e 100644 (file)
@@ -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;
+    }
 }
index 28b5619052582c63ff2d99137b555df76b4c345a..a64b5322461373653a63601bd634053862b71e93 100644 (file)
@@ -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;
+       }
 }
index a4c0ec918776f2a292adea4ad53d04ba691dd290..91d0840d3c3d5343f2f06102fb6057e5b28404ef 100644 (file)
 
 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;
+    }
 }
index 6e819daab7b73771cf8070e9fc9ceced05821aa0..a206b5dbe9933d42e751e7b37473f45740099332 100644 (file)
 
 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;
        }
index 01cbe455a0aa021e224bce6cce59fe76e6ccb73d..576a80d67ac295e59a1bbf81eff95cf1efdea407 100644 (file)
@@ -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);
+    }
 }
index 70dd6cb4f90959f05245f404b2d773e0e81107d1..2be7058127088d66781c23e926f17c065a911884 100644 (file)
@@ -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;
+       }
 }
index 6974defe408791ef06b1e4fe6877d2d94a06ddcb..763cdc2377f40fe97a8efcade15deec9e3da1988 100644 (file)
@@ -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;
+       }
 }
index f1dfbdd27ec2c9dbd1a5d0971a5d0e864d568735..d2b11921a63891eebed78aa6273373a6aa0ec1e7 100644 (file)
@@ -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;
+    }
 }
index 54db3f3f35fffa6af475cf3a9394b4c78de02b47..99961e3eda3d05d43fc9a51d8630b394f8fbdbb1 100644 (file)
@@ -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;
+    }
 }
index 36c276f377920ffcb64ae131134468abdea16dc9..7be341dab5fe35426fd5c13c1955175a1c2d05e1 100644 (file)
@@ -86,4 +86,9 @@ public final class ErrPtg extends ScalarConstantPtg {
                 throw new RuntimeException("Unexpected error code (" + code + ")");
         }
     }
+
+    @Override
+    public ErrPtg copy() {
+        return this;
+    }
 }
index 83ebc2044d4247395071f889c1d1d5fae5de69d6..66da8a23fed9b1af53b3a455c8e8edb3101b655e 100644 (file)
@@ -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;
+    }
 }
index ecfccb67b295bf34ff45804c642a2fd99cb3a4a7..6fc76a5815283c2dd9a682d81b201a43d536ed03 100644 (file)
@@ -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;
+    }
 }
index a1cacd8ba53eefd0f3d1caaddbd04fef1faf7f67..05c18a05e0963096eacbd5edde334ed531221536 100644 (file)
@@ -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;
+    }
 }
index 54ae3f7dcc60199ae9a1ff2b2cd3281ec12a9e3c..c89d1c8876c052661048afd669842c3beccc3a71 100644 (file)
@@ -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;
+    }
 }
index 8f8152b07ae2e978745c72c19660f973805d9ea9..307fb6eee7f6ffd252db3fb858b3c9962e43e70c 100644 (file)
@@ -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;
+    }
 }
index b91784edb210b3c4204e1c0c6a9422a6c2693528..f2c56f76a8bd2442988519ac9de84f99a269e312 100644 (file)
@@ -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;
+       }
 }
index 1927cb9754bea674cf49011ef5464096e2aee99e..9a641654faced844ef338a4843d7a5c487f33fcd 100644 (file)
@@ -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;
+       }
 }
index 305c4ef2e818fd54ee39507c7257393b4ee9d0ec..d7aa350c633ee8a00b66698e5857cfe23b0312d1 100644 (file)
@@ -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;
+    }
 }
index b86854f9cf15197905380f8ecc3546b4c6bd62af..f98b215cd8f9f42385756e9554f39485bad5254a 100644 (file)
 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;
+    }
 }
index 9ebca5061bda59c91af7f76044c07917043ac4d3..9dfd5cf079a9fccb4c688e12af71525ad0221128 100644 (file)
@@ -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;
+       }
 }
index 44f541da993e21bf6ffab09a965f5fd5a1decd5d..d8efb220d16d862376cda3fe81d400857ba0379a 100644 (file)
@@ -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);
+       }
 }
index 077cfe485b163258dbf5b091d0fa5478e8c00200..ed20c36e7ce339f438015cd3fd7af5dcdfaac32a 100644 (file)
@@ -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
index 84e44128738ebcdce2f6f957bf714af6441365c2..75cbd35143c6c583cd2614af05035b11c8ddab96 100644 (file)
@@ -21,10 +21,6 @@ import org.apache.poi.util.LittleEndianOutput;
 
 /**
  * Missing Function Arguments
- * 
- * Avik Sengupta &lt;avik at apache.org&gt;
- * 
- * @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;
+       }
 }
index fb4f468e3ca9be925222e9e44ed88794cb9643d1..c99e90318a9ec06fb70cfcc3f91fc24f14d16def 100644 (file)
 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;
+    }
 }
index a8632b534b6a3e46c77f0ede60c172d8cda8d296..e3c833f02487d730a9bf0eea856957635ebcfa8b 100644 (file)
@@ -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);
+       }
 }
index 4684ef40b7056c12d3c81ec6ffae9be29b157648..c1b50e20acf923f8e153497765e7b0366ea40600 100644 (file)
@@ -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;
+       }
 }
index 0b098ba768a3c576ac95ffee2e402c487e79be71..94cb7f4cea66aa195620f2048fbbe76225e9dbcb 100644 (file)
@@ -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);
+    }
 }
index c6c557a349c5a66c375a4d4e7016d9e8e6935329..07725ebfda486e3c340031db83a2853a106b9e72 100644 (file)
@@ -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;
+    }
 }
index 6cec23604b0921a3af4019777a503957fb3686f0..c226c8bee086007b9607f022c883b500c5e34730 100644 (file)
@@ -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;
+       }
 }
index 0c36a844375cee498c4047e79e0a1c4035c3fe8e..1f1ab3c761dc97967040a8f3fb034833a8a9ba5b 100644 (file)
 
 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();
 }
index 089d3c73680b32f00eaaf0e86e9ff57f1957560b..7d09d16169cb0e498599e7b961171fab12c29b6a 100644 (file)
@@ -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;
     }
index 1ea30abe20ed4997362d3f51b67d11eef3d1986c..bc63048cd52869aa2ab852a758b212ff6d13f77f 100644 (file)
@@ -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 &lt;lists@aviksengupta.com&gt; 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;
+       }
 }
index f27fb33574448528c74ba8ffaf76bdc8cec8f821..b5e6664d16aec8af32730f5c7b273a8ad1e15a6a 100644 (file)
@@ -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;
+    }
 }
index 6f5e8158e3aa667f42d963a36739b55833d39001..d7bd306b49b1b8f702bc71c7d13a052c56dd79a4 100644 (file)
 
 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;
+    }
 }
index a7649482e76e5945d6b12785099e7abdcc6695c4..b85df16887d2eabb2f4cc15cfd1acbfa30a44a0e 100644 (file)
@@ -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();
 }
index 6918f78ab98fecdd225aad476e30eb431544046e..35b43414c7cb7c4f68e5d3d6e3bcbf5a4579dbc8 100644 (file)
@@ -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;
+    }
 }
index 81a4b381f38b835510b1a6b7fa583acf8a1956be..c0d0566b5447fee563a9e71c556f2758db6f08fb 100644 (file)
@@ -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);
        }
index e5506f3668cc7101a544f92ba2dfe13735deccfa..34105ee6735caefb1e95cdb89ae93ebb18dceaf1 100644 (file)
@@ -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);
+    }
 }
index 8ff8c7effccdf36ead69c20ac07b07cf36b7a67b..5327650dc073e1d447157d301c21900d0a8c3879 100644 (file)
@@ -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);
+    }
 }
index e450644b8f370d8b0362473f38baffee172e027a..7027d5ccf4806934620f8b828d7cceb416c26388 100644 (file)
@@ -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);
+    }
 }
index 90d43ca94591c3e2aa9ae3c540cdbd6d4fd1ea2c..faf6e9ab8da72a35b4ae6181ea3d338813bcf0e1 100644 (file)
@@ -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);
+    }
 }
index 297c0e7d899638d6c54b9b3f4a64732860abb95d..0f9811a4bb3f34b9013dfd4badd05a316267abcb 100644 (file)
@@ -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);
+       }
 }
index 31a3a56be7aa743910e01d425b8957b94af45f2f..34f9747ce501fcc44ca594f45e0fb01ca69c6325 100644 (file)
@@ -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) {
index 210d887df4d9767b6d5684bfe32f8fd0116f0e92..d4e4827f552adfa4516f79b768ca676701427a59 100644 (file)
@@ -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();
        }
+
+
 }
index c9b8e535460d40e563c5dab7d580965e2bd8ce36..d9fbd27417f46e0e14b711d3c7e0b58ab6086496 100644 (file)
@@ -24,10 +24,6 @@ import org.apache.poi.util.StringUtil;
 /**
  * String Stores a String value in a formula value stored in the format
  * &lt;length 2 bytes&gt;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;
+    }
 }
index 5ae6ec7a9ff2464f9ee7495c84de9ec0a1d8d73c..54e7817f5b16a4b0f5a438ed1f7e05993ed9a0d2 100644 (file)
 
 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;
+    }
 }
index b8a2109b561fa04ca50ca6371980ef4e4a080b89..1d37e6672c4a38472b50cdf768a329c6c2e452d5 100644 (file)
@@ -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;
+    }
 }
index 54b423e82f8f9a2720dab72c3ab53ceae642bd71..a2579778263d2ef67ac7e82e304612832546b1eb 100644 (file)
 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;
+    }
 }
index be6ba540d6b5b2088b56a3cbb0fa20fa956b49e6..68a0d0e1ae6439c2a4eb15dbafcc294286202220 100644 (file)
 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;
+    }
 }
index 45042df0f92f745ae6aa523b7ddb5de74b571cf2..681f9efc54ef700a42fd9ef9cade63421528f6de 100644 (file)
@@ -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;
+    }
 }
index 8eac21208e808dd02a4ca1a7e675bf39f5dab7ad..9992cadf9af6317c47dca544f59f877514528047 100644 (file)
@@ -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;
+    }
 }
index 1194adfd2acc8a6ca8f76b458da9eabc675f7f07..a3e595df044e98f0fa47f6f41c8698461e86751f 100644 (file)
@@ -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)
         */
index 2b65ae660efed3d2583d444a2f67f9c864edfa50..c466f275cc4f53a47cbd755757c4f93a1cab2601 100644 (file)
@@ -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) {
index 1224e479d6fb223ae2f405b6b87f56e61bb37f36..bef4596743f498d9923c0b15bd0b9828d4331604 100644 (file)
 
 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() +
index e948465567f186f5251a547f38a98541a19339ab..766e2e3564ef5273d4ce0b331f953c8c238bec8d 100644 (file)
@@ -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();
        }
 }
index 921b820b842a0c6360b0e713056fc7346d7a3f13..db68883edf0498db28a449d75faf6791681acbd6 100644 (file)
 
 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
index ed6851a1c6d5f7487cf04cefdad4cb3e4317e16b..39d3d8f0ee636e6313127d6ef2434debffe942b4 100644 (file)
@@ -25,6 +25,7 @@ import static org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.ByteBuffer;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.security.MessageDigest;
@@ -56,43 +57,34 @@ import org.apache.poi.util.LittleEndian;
 /**
  * Decryptor implementation for Agile Encryption
  */
-public class AgileDecryptor extends Decryptor implements Cloneable {
+public class AgileDecryptor extends Decryptor {
+    static final byte[] kVerifierInputBlock = longToBytes(0xfea7d2763b4b9e79L);
+    static final byte[] kHashedVerifierBlock = longToBytes(0xd7aa0f6d3061344eL);
+    static final byte[] kCryptoKeyBlock = longToBytes(0x146e0be7abacd0d6L);
+    static final byte[] kIntegrityKeyBlock = longToBytes(0x5fb2ad010cb9e1f6L);
+    static final byte[] kIntegrityValueBlock = longToBytes(0xa0677f02b22c8433L);
+
     private long _length = -1;
 
-    /* package */ static final byte[] kVerifierInputBlock;
-    /* package */ static final byte[] kHashedVerifierBlock;
-    /* package */ static final byte[] kCryptoKeyBlock;
-    /* package */ static final byte[] kIntegrityKeyBlock;
-    /* package */ static final byte[] kIntegrityValueBlock;
-
-    static {
-        kVerifierInputBlock =
-            new byte[] { (byte)0xfe, (byte)0xa7, (byte)0xd2, (byte)0x76,
-                         (byte)0x3b, (byte)0x4b, (byte)0x9e, (byte)0x79 };
-        kHashedVerifierBlock =
-            new byte[] { (byte)0xd7, (byte)0xaa, (byte)0x0f, (byte)0x6d,
-                         (byte)0x30, (byte)0x61, (byte)0x34, (byte)0x4e };
-        kCryptoKeyBlock =
-            new byte[] { (byte)0x14, (byte)0x6e, (byte)0x0b, (byte)0xe7,
-                         (byte)0xab, (byte)0xac, (byte)0xd0, (byte)0xd6 };
-        kIntegrityKeyBlock =
-            new byte[] { (byte)0x5f, (byte)0xb2, (byte)0xad, (byte)0x01, 
-                         (byte)0x0c, (byte)0xb9, (byte)0xe1, (byte)0xf6 };
-        kIntegrityValueBlock =
-            new byte[] { (byte)0xa0, (byte)0x67, (byte)0x7f, (byte)0x02,
-                         (byte)0xb2, (byte)0x2c, (byte)0x84, (byte)0x33 };
+    protected AgileDecryptor() {
     }
 
-    protected AgileDecryptor() {
+    protected AgileDecryptor(AgileDecryptor other) {
+        super(other);
+        _length = other._length;
+    }
+
+    private static byte[] longToBytes(long l) {
+        return ByteBuffer.allocate(Long.BYTES).putLong(l).array();
     }
-    
+
     /**
      * set decryption password
      */
     @Override
     public boolean verifyPassword(String password) throws GeneralSecurityException {
         AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
-        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); 
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
 
         int blockSize = header.getBlockSize();
 
@@ -130,7 +122,7 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
          */
         byte[] verifierHashDec = hashInput(ver, pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
         verifierHashDec = getBlock0(verifierHashDec, ver.getHashAlgorithm().hashSize);
-        
+
         /**
          * encryptedKeyValue: This attribute MUST be generated by using the following steps:
          * 1. Generate a random array of bytes that is the same size as specified by the
@@ -180,7 +172,7 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
         cipher = getCipher(secretKey, cipherAlgo, ver.getChainingMode(), vec, Cipher.DECRYPT_MODE);
         byte[] hmacValue = cipher.doFinal(header.getEncryptedHmacValue());
         hmacValue = getBlock0(hmacValue, header.getHashAlgorithm().hashSize);
-        
+
         if (Arrays.equals(verifierHashDec, verifierHash)) {
             setSecretKey(secretKey);
             setIntegrityHmacKey(hmacKey);
@@ -194,7 +186,7 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
     /**
      * instead of a password, it's also possible to decrypt via certificate.
      * Warning: this code is experimental and hasn't been validated
-     * 
+     *
      * @see <a href="http://social.msdn.microsoft.com/Forums/en-US/cc9092bb-0c82-4b5b-ae21-abf643bdb37c/agile-encryption-with-certificates">Agile encryption with certificates</a>
      *
      * @param keyPair
@@ -208,7 +200,7 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
         HashAlgorithm hashAlgo = header.getHashAlgorithm();
         CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
         int blockSize = header.getBlockSize();
-        
+
         AgileCertificateEntry ace = null;
         for (AgileCertificateEntry aceEntry : ver.getCertificates()) {
             if (x509.equals(aceEntry.x509)) {
@@ -219,12 +211,12 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
         if (ace == null) {
             return false;
         }
-        
+
         Cipher cipher = Cipher.getInstance("RSA");
         cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
         byte[] keyspec = cipher.doFinal(ace.encryptedKey);
         SecretKeySpec secretKey = new SecretKeySpec(keyspec, ver.getCipherAlgorithm().jceId);
-        
+
         Mac x509Hmac = CryptoFunctions.getMac(hashAlgo);
         x509Hmac.init(secretKey);
         byte[] certVerifier = x509Hmac.doFinal(ace.x509.getEncoded());
@@ -238,8 +230,8 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
         cipher = getCipher(secretKey, cipherAlgo, header.getChainingMode(), vec, Cipher.DECRYPT_MODE);
         byte[] hmacValue = cipher.doFinal(header.getEncryptedHmacValue());
         hmacValue = getBlock0(hmacValue, hashAlgo.hashSize);
-        
-        
+
+
         if (Arrays.equals(ace.certVerifier, certVerifier)) {
             setSecretKey(secretKey);
             setIntegrityHmacKey(hmacKey);
@@ -268,7 +260,7 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
         byte[] iv = generateIv(hashAlgo, ver.getSalt(), null, blockSize);
         Cipher cipher = getCipher(skey, cipherAlgo, chainMode, iv, cipherMode);
         byte[] hashFinal;
-        
+
         try {
             inputKey = getBlock0(inputKey, getNextBlockSize(inputKey.length, blockSize));
             hashFinal = cipher.doFinal(inputKey);
@@ -314,13 +306,13 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
         }
 
         existing.init(encryptionMode, skey, aps);
-        
+
         return existing;
     }
 
     /**
      * 2.3.4.15 Data Encryption (Agile Encryption)
-     * 
+     *
      * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly
      * random access while allowing CBC modes to be used in the encryption process.
      * The initialization vector for the encryption process MUST be obtained by using the zero-based
@@ -341,16 +333,16 @@ public class AgileDecryptor extends Decryptor implements Cloneable {
 
         // TODO: calculate integrity hmac while reading the stream
         // for a post-validation of the data
-        
+
         @Override
         protected Cipher initCipherForBlock(Cipher cipher, int block)
         throws GeneralSecurityException {
             return AgileDecryptor.initCipherForBlock(cipher, block, false, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE);
         }
     }
-    
+
     @Override
-    public AgileDecryptor clone() throws CloneNotSupportedException {
-        return (AgileDecryptor)super.clone();
+    public AgileDecryptor copy() {
+        return new AgileDecryptor(this);
     }
 }
index d943014bc0a5033841f8e88cb02bfdba3bb1c211..0c4983e65e749115f7e231ff99054c6fc9f9d9e3 100644 (file)
@@ -30,14 +30,20 @@ import org.apache.poi.poifs.crypt.EncryptionHeader;
 import org.apache.poi.poifs.crypt.HashAlgorithm;
 import org.apache.poi.util.GenericRecordUtil;
 
-public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable {
+public class AgileEncryptionHeader extends EncryptionHeader {
     private byte[] encryptedHmacKey;
     private byte[] encryptedHmacValue;
-    
+
     public AgileEncryptionHeader(String descriptor) {
         this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
     }
-    
+
+    public AgileEncryptionHeader(AgileEncryptionHeader other) {
+        super(other);
+        encryptedHmacKey = (other.encryptedHmacKey == null) ? null : other.encryptedHmacKey.clone();
+        encryptedHmacValue = (other.encryptedHmacValue == null) ? null : other.encryptedHmacValue.clone();
+    }
+
     protected AgileEncryptionHeader(EncryptionDocument ed) {
         CTKeyData keyData;
         try {
@@ -50,7 +56,7 @@ public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable
         }
 
         int keyBits = (int)keyData.getKeyBits();
-        
+
         CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), keyBits);
         setCipherAlgorithm(ca);
         setCipherProvider(ca.provider);
@@ -71,14 +77,14 @@ public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable
         default:
             throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
         }
-    
+
         int hashSize = keyData.getHashSize();
-        
+
         HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString());
         setHashAlgorithm(ha);
 
         if (getHashAlgorithm().hashSize != hashSize) {
-            throw new EncryptedDocumentException("Unsupported hash algorithm: " + 
+            throw new EncryptedDocumentException("Unsupported hash algorithm: " +
                     keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
         }
 
@@ -87,13 +93,13 @@ public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable
         if (getKeySalt().length != saltLength) {
             throw new EncryptedDocumentException("Invalid salt length");
         }
-        
+
         CTDataIntegrity di = ed.getEncryption().getDataIntegrity();
         setEncryptedHmacKey(di.getEncryptedHmacKey());
         setEncryptedHmacValue(di.getEncryptedHmacValue());
     }
-    
-    
+
+
     public AgileEncryptionHeader(CipherAlgorithm algorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
         setCipherAlgorithm(algorithm);
         setHashAlgorithm(hashAlgorithm);
@@ -127,14 +133,6 @@ public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable
         this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
     }
 
-    @Override
-    public AgileEncryptionHeader clone() throws CloneNotSupportedException {
-        AgileEncryptionHeader other = (AgileEncryptionHeader)super.clone();
-        other.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone();
-        other.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
-        return other;
-    }
-
     @Override
     public Map<String, Supplier<?>> getGenericProperties() {
         return GenericRecordUtil.getGenericProperties(
@@ -143,4 +141,9 @@ public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable
             "encryptedHmacValue", this::getEncryptedHmacValue
         );
     }
+
+    @Override
+    public AgileEncryptionHeader copy() {
+        return new AgileEncryptionHeader(this);
+    }
 }
index 2e8ba701662c74c1f798fec80abccd002735f6c0..40179bb81e7f4aa87624590dea21f7d389ad34a9 100644 (file)
@@ -24,37 +24,44 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChainingMode;
-import org.apache.poi.poifs.crypt.CipherAlgorithm;
-import org.apache.poi.poifs.crypt.EncryptionVerifier;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
-
 import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor;
 import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
 import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
 import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor;
 import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.EncryptionVerifier;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
 
 /**
- * Used when checking if a key is valid for a document 
+ * Used when checking if a key is valid for a document
  */
-public class AgileEncryptionVerifier extends EncryptionVerifier implements Cloneable {
+public class AgileEncryptionVerifier extends EncryptionVerifier {
 
     public static class AgileCertificateEntry {
         X509Certificate x509;
         byte[] encryptedKey;
         byte[] certVerifier;
+
+        public AgileCertificateEntry() {}
+
+        public AgileCertificateEntry(AgileCertificateEntry other) {
+            x509 = other.x509;
+            encryptedKey = (other.encryptedKey == null) ? null : other.encryptedKey.clone();
+            certVerifier = (other.certVerifier == null) ? null : other.certVerifier.clone();
+        }
     }
-    
-    private List<AgileCertificateEntry> certList = new ArrayList<>();
+
+    private final List<AgileCertificateEntry> certList = new ArrayList<>();
     private int keyBits = -1;
     private int blockSize = -1;
 
     public AgileEncryptionVerifier(String descriptor) {
         this(AgileEncryptionInfoBuilder.parseDescriptor(descriptor));
     }
-    
+
     protected AgileEncryptionVerifier(EncryptionDocument ed) {
         Iterator<CTKeyEncryptor> encList = ed.getEncryption().getKeyEncryptors().getKeyEncryptorList().iterator();
         CTPasswordKeyEncryptor keyData;
@@ -66,37 +73,37 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
         } catch (Exception e) {
             throw new EncryptedDocumentException("Unable to parse keyData", e);
         }
-        
+
         int kb = (int)keyData.getKeyBits();
         CipherAlgorithm ca = CipherAlgorithm.fromXmlId(keyData.getCipherAlgorithm().toString(), kb);
         setCipherAlgorithm(ca);
 
         setKeySize(kb);
-        
+
         int blockSize = keyData.getBlockSize();
         setBlockSize(blockSize);
-        
+
         int hashSize = keyData.getHashSize();
 
         HashAlgorithm ha = HashAlgorithm.fromEcmaId(keyData.getHashAlgorithm().toString());
         setHashAlgorithm(ha);
 
         if (getHashAlgorithm().hashSize != hashSize) {
-            throw new EncryptedDocumentException("Unsupported hash algorithm: " + 
+            throw new EncryptedDocumentException("Unsupported hash algorithm: " +
                     keyData.getHashAlgorithm() + " @ " + hashSize + " bytes");
         }
 
         setSpinCount(keyData.getSpinCount());
         setEncryptedVerifier(keyData.getEncryptedVerifierHashInput());
         setSalt(keyData.getSaltValue());
-        setEncryptedKey(keyData.getEncryptedKeyValue()); 
+        setEncryptedKey(keyData.getEncryptedKeyValue());
         setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
 
         int saltSize = keyData.getSaltSize();
         if (saltSize != getSalt().length) {
             throw new EncryptedDocumentException("Invalid salt size");
         }
-        
+
         switch (keyData.getCipherChaining().intValue()) {
             case STCipherChaining.INT_CHAINING_MODE_CBC:
                 setChainingMode(ChainingMode.cbc);
@@ -107,11 +114,11 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
             default:
                 throw new EncryptedDocumentException("Unsupported chaining mode - "+ keyData.getCipherChaining());
         }
-        
+
         if (!encList.hasNext()) {
             return;
         }
-        
+
         try {
             CertificateFactory cf = CertificateFactory.getInstance("X.509");
             while (encList.hasNext()) {
@@ -126,7 +133,7 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
             throw new EncryptedDocumentException("can't parse X509 certificate", e);
         }
     }
-    
+
     public AgileEncryptionVerifier(CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
         setCipherAlgorithm(cipherAlgorithm);
         setHashAlgorithm(hashAlgorithm);
@@ -135,7 +142,14 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
         setBlockSize(blockSize);
         setSpinCount(100000); // TODO: use parameter
     }
-    
+
+    public AgileEncryptionVerifier(AgileEncryptionVerifier other) {
+        super(other);
+        keyBits = other.keyBits;
+        blockSize = other.blockSize;
+        other.certList.stream().map(AgileCertificateEntry::new).forEach(certList::add);
+    }
+
     @Override
     protected void setSalt(byte[] salt) {
         if (salt == null || salt.length != getCipherAlgorithm().blockSize) {
@@ -143,7 +157,7 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
         }
         super.setSalt(salt);
     }
-    
+
     // make method visible for this package
     @Override
     protected void setEncryptedVerifier(byte[] encryptedVerifier) {
@@ -161,26 +175,23 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
     protected void setEncryptedKey(byte[] encryptedKey) {
         super.setEncryptedKey(encryptedKey);
     }
-    
+
     public void addCertificate(X509Certificate x509) {
         AgileCertificateEntry ace = new AgileCertificateEntry();
         ace.x509 = x509;
         certList.add(ace);
     }
-    
+
     public List<AgileCertificateEntry> getCertificates() {
         return certList;
     }
 
     @Override
-    public AgileEncryptionVerifier clone() throws CloneNotSupportedException {
-        AgileEncryptionVerifier other = (AgileEncryptionVerifier)super.clone();
-        // TODO: deep copy of certList
-        other.certList = new ArrayList<>(certList);
-        return other;
-    }
-    
-    
+    public AgileEncryptionVerifier copy() {
+        return new AgileEncryptionVerifier(this);
+    }
+
+
     /**
      * The keysize (in bits) of the verifier data. This usually equals the keysize of the header,
      * but only on a few exceptions, like files generated by Office for Mac, can be
@@ -192,7 +203,7 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
         return keyBits;
     }
 
-    
+
     /**
      * The blockSize (in bytes) of the verifier data.
      * This usually equals the blocksize of the header.
@@ -202,7 +213,7 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
     public int getBlockSize() {
         return blockSize;
     }
-    
+
     /**
      * Sets the keysize (in bits) of the verifier
      *
@@ -218,7 +229,7 @@ public class AgileEncryptionVerifier extends EncryptionVerifier implements Clone
         throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for cipher "+getCipherAlgorithm());
     }
 
-    
+
     /**
      * Sets the blockSize (in bytes) of the verifier
      *
index 93a412225f04b6ea458b0901c034a1d15741e07e..4c9b10d49b958c5232ef4b76a26a353372fb932e 100644 (file)
@@ -49,6 +49,17 @@ import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
+import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
+import com.microsoft.schemas.office.x2006.encryption.CTEncryption;
+import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
+import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor;
+import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptors;
+import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
+import com.microsoft.schemas.office.x2006.encryption.STCipherAlgorithm;
+import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
+import com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm;
+import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor;
+import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
 import org.apache.poi.EncryptedDocumentException;
 import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
 import org.apache.poi.poifs.crypt.CryptoFunctions;
@@ -65,28 +76,21 @@ import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 import org.apache.poi.util.LittleEndianConsts;
 import org.apache.xmlbeans.XmlOptions;
 
-import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
-import com.microsoft.schemas.office.x2006.encryption.CTEncryption;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptor;
-import com.microsoft.schemas.office.x2006.encryption.CTKeyEncryptors;
-import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
-import com.microsoft.schemas.office.x2006.encryption.STCipherAlgorithm;
-import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
-import com.microsoft.schemas.office.x2006.encryption.STHashAlgorithm;
-import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor;
-import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
-
-public class AgileEncryptor extends Encryptor implements Cloneable {
+public class AgileEncryptor extends Encryptor {
 
     //arbitrarily selected; may need to increase
     private static final int MAX_RECORD_LENGTH = 1_000_000;
 
     private byte[] integritySalt;
     private byte[] pwHash;
-    
-       protected AgileEncryptor() {
-       }
+
+       protected AgileEncryptor() {}
+
+    protected AgileEncryptor(AgileEncryptor other) {
+           super(other);
+           integritySalt = (other.integritySalt == null) ? null : other.integritySalt.clone();
+           pwHash = (other.pwHash == null) ? null : other.pwHash.clone();
+    }
 
     @Override
     public void confirmPassword(String password) {
@@ -96,7 +100,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         int blockSize = header.getBlockSize();
         int keySize = header.getKeySize()/8;
         int hashSize = header.getHashAlgorithm().hashSize;
-        
+
         byte[] newVerifierSalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
              , newVerifier = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
              , newKeySalt = IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH)
@@ -107,10 +111,10 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         r.nextBytes(newKeySalt); // blocksize
         r.nextBytes(newKeySpec); // keysize
         r.nextBytes(newIntegritySalt); // hashsize
-        
+
         confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt);
     }
-       
+
        @Override
     public void confirmPassword(String password, byte[] keySpec, byte[] keySalt, byte[] verifier, byte[] verifierSalt, byte[] integritySalt) {
         AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
@@ -120,9 +124,9 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         header.setKeySalt(keySalt);
 
         int blockSize = header.getBlockSize();
-           
+
         pwHash = hashPassword(password, ver.getHashAlgorithm(), verifierSalt, ver.getSpinCount());
-        
+
         /**
          * encryptedVerifierHashInput: This attribute MUST be generated by using the following steps:
          * 1. Generate a random array of bytes with the number of bytes used specified by the saltSize
@@ -138,7 +142,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
          */
         byte[] encryptedVerifier = hashInput(ver, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
         ver.setEncryptedVerifier(encryptedVerifier);
-           
+
 
         /**
          * encryptedVerifierHashValue: This attribute MUST be generated by using the following steps:
@@ -156,7 +160,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         byte[] hashedVerifier = hashMD.digest(verifier);
         byte[] encryptedVerifierHash = hashInput(ver, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
         ver.setEncryptedVerifierHash(encryptedVerifierHash);
-        
+
         /**
          * encryptedKeyValue: This attribute MUST be generated by using the following steps:
          * 1. Generate a random array of bytes that is the same size as specified by the
@@ -172,13 +176,13 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
          */
         byte[] encryptedKey = hashInput(ver, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
         ver.setEncryptedKey(encryptedKey);
-        
+
         SecretKey secretKey = new SecretKeySpec(keySpec, header.getCipherAlgorithm().jceId);
         setSecretKey(secretKey);
-        
+
         /*
          * 2.3.4.14 DataIntegrity Generation (Agile Encryption)
-         * 
+         *
          * The DataIntegrity element contained within an Encryption element MUST be generated by using
          * the following steps:
          * 1. Obtain the intermediate key by decrypting the encryptedKeyValue from a KeyEncryptor
@@ -198,7 +202,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
          *    used as the message.
          * 6. Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
          *    0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
-         * 7.  Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6. 
+         * 7.  Assign the encryptedHmacValue attribute to the base64-encoded form of the result of step 6.
          */
         this.integritySalt = integritySalt.clone();
 
@@ -221,7 +225,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
             throw new EncryptedDocumentException(e);
         }
        }
-       
+
     @Override
     public OutputStream getDataStream(DirectoryNode dir)
             throws IOException, GeneralSecurityException {
@@ -230,11 +234,11 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
     }
 
     /**
-     * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message), 
-     * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key. 
-     * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be 
+     * Generate an HMAC, as specified in [RFC2104], of the encrypted form of the data (message),
+     * which the DataIntegrity element will verify by using the Salt generated in step 2 as the key.
+     * Note that the entire EncryptedPackage stream (1), including the StreamSize field, MUST be
      * used as the message.
-     * 
+     *
      * Encrypt the HMAC as in step 3 by using a blockKey byte array consisting of the following bytes:
      * 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, and 0x33.
      **/
@@ -266,22 +270,22 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         byte[] iv = CryptoFunctions.generateIv(header.getHashAlgorithm(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
         Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE);
         byte[] encryptedHmacValue = cipher.doFinal(hmacValueFilled);
-        
+
         header.setEncryptedHmacValue(encryptedHmacValue);
     }
-    
-    private final CTKeyEncryptor.Uri.Enum passwordUri = 
+
+    private final CTKeyEncryptor.Uri.Enum passwordUri =
         CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_PASSWORD;
-    private final CTKeyEncryptor.Uri.Enum certificateUri = 
+    private final CTKeyEncryptor.Uri.Enum certificateUri =
         CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE;
-    
+
     protected EncryptionDocument createEncryptionDocument() {
         AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
-        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); 
-        
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
+
         EncryptionDocument ed = EncryptionDocument.Factory.newInstance();
         CTEncryption edRoot = ed.addNewEncryption();
-        
+
         CTKeyData keyData = edRoot.addNewKeyData();
         CTKeyEncryptors keyEncList = edRoot.addNewKeyEncryptors();
         CTKeyEncryptor keyEnc = keyEncList.addNewKeyEncryptor();
@@ -289,10 +293,10 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         CTPasswordKeyEncryptor keyPass = keyEnc.addNewEncryptedPasswordKey();
 
         keyPass.setSpinCount(ver.getSpinCount());
-        
+
         keyData.setSaltSize(header.getBlockSize());
         keyPass.setSaltSize(ver.getBlockSize());
-        
+
         keyData.setBlockSize(header.getBlockSize());
         keyPass.setBlockSize(ver.getBlockSize());
 
@@ -312,9 +316,9 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         }
         keyData.setCipherAlgorithm(xmlCipherAlgo);
         keyPass.setCipherAlgorithm(xmlCipherAlgo);
-        
+
         switch (header.getChainingMode()) {
-        case cbc: 
+        case cbc:
             keyData.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC);
             keyPass.setCipherChaining(STCipherChaining.CHAINING_MODE_CBC);
             break;
@@ -325,7 +329,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         default:
             throw new EncryptedDocumentException("ChainingMode "+header.getChainingMode()+" not supported.");
         }
-        
+
         keyData.setHashAlgorithm(mapHashAlgorithm(header.getHashAlgorithm()));
         keyPass.setHashAlgorithm(mapHashAlgorithm(ver.getHashAlgorithm()));
 
@@ -334,11 +338,11 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         keyPass.setEncryptedVerifierHashInput(ver.getEncryptedVerifier());
         keyPass.setEncryptedVerifierHashValue(ver.getEncryptedVerifierHash());
         keyPass.setEncryptedKeyValue(ver.getEncryptedKey());
-        
+
         CTDataIntegrity hmacData = edRoot.addNewDataIntegrity();
         hmacData.setEncryptedHmacKey(header.getEncryptedHmacKey());
         hmacData.setEncryptedHmacValue(header.getEncryptedHmacValue());
-        
+
         for (AgileCertificateEntry ace : ver.getCertificates()) {
             keyEnc = keyEncList.addNewKeyEncryptor();
             keyEnc.setUri(certificateUri);
@@ -351,7 +355,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
             certData.setEncryptedKeyValue(ace.encryptedKey);
             certData.setCertVerifier(ace.certVerifier);
         }
-        
+
         return ed;
     }
 
@@ -362,7 +366,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         }
         return xmlHashAlgo;
     }
-    
+
     protected void marshallEncryptionDocument(EncryptionDocument ed, LittleEndianByteArrayOutputStream os) {
         XmlOptions xo = new XmlOptions();
         xo.setCharacterEncoding("UTF-8");
@@ -396,7 +400,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         EncryptionRecord er = new EncryptionRecord(){
             @Override
             public void write(LittleEndianByteArrayOutputStream bos) {
-                // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where 
+                // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where
                 // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004
                 bos.writeShort(info.getVersionMajor());
                 bos.writeShort(info.getVersionMinor());
@@ -407,14 +411,14 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
                 marshallEncryptionDocument(ed, bos);
             }
         };
-        
+
         createEncryptionEntry(dir, "EncryptionInfo", er);
     }
-    
-    
+
+
     /**
      * 2.3.4.15 Data Encryption (Agile Encryption)
-     * 
+     *
      * The EncryptedPackage stream (1) MUST be encrypted in 4096-byte segments to facilitate nearly
      * random access while allowing CBC modes to be used in the encryption process.
      * The initialization vector for the encryption process MUST be obtained by using the zero-based
@@ -431,7 +435,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         public AgileCipherOutputStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
             super(dir, 4096);
         }
-        
+
         @Override
         protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
         throws GeneralSecurityException {
@@ -442,9 +446,9 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
         protected void calculateChecksum(File fileOut, int oleStreamSize)
         throws GeneralSecurityException, IOException {
             // integrityHMAC needs to be updated before the encryption document is created
-            updateIntegrityHMAC(fileOut, oleStreamSize); 
+            updateIntegrityHMAC(fileOut, oleStreamSize);
         }
-        
+
         @Override
         protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
         throws IOException, GeneralSecurityException {
@@ -453,10 +457,7 @@ public class AgileEncryptor extends Encryptor implements Cloneable {
     }
 
     @Override
-    public AgileEncryptor clone() throws CloneNotSupportedException {
-        AgileEncryptor other = (AgileEncryptor)super.clone();
-        other.integritySalt = (integritySalt == null) ? null : integritySalt.clone();
-        other.pwHash = (pwHash == null) ? null : pwHash.clone();
-        return other;
+    public AgileEncryptor copy() {
+        return new AgileEncryptor(this);
     }
 }
index ba366b5317ffd0313470e117fa5178f1ac83bfdb..9e03d694d9adc20064386fb9fb2ee01c301a78f6 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel;
 
 import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
 
+import org.apache.poi.common.Duplicatable;
 import org.apache.poi.ooxml.POIXMLException;
 import org.apache.poi.ss.usermodel.BorderStyle;
 import org.apache.poi.ss.usermodel.CellStyle;
@@ -29,6 +30,7 @@ import org.apache.poi.ss.usermodel.IndexedColors;
 import org.apache.poi.ss.usermodel.ReadingOrder;
 import org.apache.poi.ss.usermodel.VerticalAlignment;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
 import org.apache.poi.xssf.model.StylesTable;
 import org.apache.poi.xssf.model.ThemesTable;
 import org.apache.poi.xssf.usermodel.extensions.XSSFCellAlignment;
@@ -56,7 +58,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
  * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getCellStyleAt(int)
  * @see org.apache.poi.xssf.usermodel.XSSFCell#setCellStyle(org.apache.poi.ss.usermodel.CellStyle)
  */
-public class XSSFCellStyle implements CellStyle {
+public class XSSFCellStyle implements CellStyle, Duplicatable {
 
     private int _cellXfId;
     private final StylesTable _stylesSource;
@@ -1303,6 +1305,14 @@ public class XSSFCellStyle implements CellStyle {
         return _cellXf.toString().equals(cf.getCoreXf().toString());
     }
 
+    @Override
+    @SuppressWarnings("squid:S2975")
+    @Deprecated
+    @Removal(version = "5.0.0")
+    public XSSFCellStyle clone() {
+        return copy();
+    }
+
     /**
      * Make a copy of this style. The underlying CTXf bean is cloned,
      * the references to fills and borders remain.
@@ -1310,7 +1320,7 @@ public class XSSFCellStyle implements CellStyle {
      * @return a copy of this style
      */
     @Override
-    public Object clone(){
+    public XSSFCellStyle copy(){
         CTXf xf = (CTXf)_cellXf.copy();
 
         int xfSize = _stylesSource._getStyleXfsSize();
index 74e94599237c4410f72d3834732cdb774e4f24fe..041f39423f93daa7b5f06680ea5416ae64fd8832 100644 (file)
@@ -23,10 +23,28 @@ public class HemfPenStyle extends HwmfPenStyle {
 
     private float[] dashPattern;
 
+    public HemfPenStyle(int flag) {
+        super(flag);
+    }
+
+    public HemfPenStyle(HemfPenStyle other) {
+        super(other);
+        dashPattern = (other.dashPattern == null) ? null : other.dashPattern.clone();
+    }
+
+    public static HemfPenStyle valueOf(
+            HwmfLineCap cap, HwmfLineJoin join, HwmfLineDash dash, boolean isAlternateDash, boolean isGeometric) {
+        int flag = 0;
+        flag = SUBSECTION_DASH.setValue(flag, dash.wmfFlag);
+        flag = SUBSECTION_ENDCAP.setValue(flag, cap.wmfFlag);
+        flag = SUBSECTION_JOIN.setValue(flag, join.wmfFlag);
+        flag = SUBSECTION_ALTERNATE.setBoolean(flag, isAlternateDash);
+        flag = SUBSECTION_GEOMETRIC.setBoolean(flag, isGeometric);
+        return new HemfPenStyle(flag);
+    }
+
     public static HemfPenStyle valueOf(int flag) {
-        HemfPenStyle ps = new HemfPenStyle();
-        ps.flag = flag;
-        return ps;
+        return new HemfPenStyle(flag);
     }
 
     @Override
@@ -39,7 +57,7 @@ public class HemfPenStyle extends HwmfPenStyle {
     }
 
     @Override
-    public HemfPenStyle clone() {
-        return (HemfPenStyle)super.clone();
+    public HemfPenStyle copy() {
+        return new HemfPenStyle(this);
     }
 }
index 7f03fb37d227b1bc02d4119d39e4eb0f4bec72bf..aaae9f5c1046cfe9ded6adf33710955c0a062081 100644 (file)
@@ -34,13 +34,16 @@ import java.util.function.Supplier;
 import org.apache.poi.common.usermodel.GenericRecord;
 import org.apache.poi.hemf.draw.HemfDrawProperties;
 import org.apache.poi.hemf.draw.HemfGraphics;
+import org.apache.poi.hemf.record.emf.HemfPenStyle;
 import org.apache.poi.hemf.record.emfplus.HemfPlusBrush.EmfPlusBrush;
 import org.apache.poi.hemf.record.emfplus.HemfPlusDraw.EmfPlusUnitType;
 import org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
 import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
 import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
 import org.apache.poi.hemf.record.emfplus.HemfPlusPath.EmfPlusPath;
-import org.apache.poi.hwmf.record.HwmfPenStyle;
+import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineCap;
+import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineDash;
+import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineJoin;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.Internal;
@@ -506,55 +509,45 @@ public class HemfPlusPen {
 
             brush.applyPen(ctx, continuedObjectData);
             prop.setPenWidth(penWidth);
-            prop.setPenStyle(new HwmfPenStyle(){
-                @Override
-                public HwmfLineCap getLineCap() {
-                    // ignore endCap for now
-                    switch(startCap) {
-                        default:
-                        case FLAT:
-                            return HwmfLineCap.FLAT;
-                        case ROUND:
-                            return HwmfLineCap.ROUND;
-                        case SQUARE:
-                            return HwmfLineCap.SQUARE;
-                    }
-                }
 
-                @Override
-                public HwmfLineJoin getLineJoin() {
-                    switch (join) {
-                        default:
-                        case BEVEL:
-                            return HwmfLineJoin.BEVEL;
-                        case ROUND:
-                            return HwmfLineJoin.ROUND;
-                        case MITER_CLIPPED:
-                        case MITER:
-                            return HwmfLineJoin.MITER;
-                    }
-                }
+            HwmfLineCap cap;
+            // ignore endCap for now
+            switch(startCap) {
+                default:
+                case FLAT:
+                    cap = HwmfLineCap.FLAT;
+                    break;
+                case ROUND:
+                    cap = HwmfLineCap.ROUND;
+                    break;
+                case SQUARE:
+                    cap = HwmfLineCap.SQUARE;
+                    break;
+            }
 
-                @Override
-                public HwmfLineDash getLineDash() {
-                    return dashedLineData == null ? HwmfLineDash.SOLID : HwmfLineDash.USERSTYLE;
-                }
+            HwmfLineJoin lineJoin;
+            switch (join) {
+                default:
+                case BEVEL:
+                    lineJoin = HwmfLineJoin.BEVEL;
+                    break;
+                case ROUND:
+                    lineJoin = HwmfLineJoin.ROUND;
+                    break;
+                case MITER_CLIPPED:
+                case MITER:
+                    lineJoin = HwmfLineJoin.MITER;
+                    break;
+            }
 
-                @Override
-                public float[] getLineDashes() {
-                    return dashedLineData;
-                }
+            HwmfLineDash lineDash = (dashedLineData == null) ? HwmfLineDash.SOLID : HwmfLineDash.USERSTYLE;
 
-                @Override
-                public boolean isAlternateDash() {
-                    return (getLineDash() != HwmfLineDash.SOLID && dashOffset != null && dashOffset == 0);
-                }
+            boolean isAlternate = (lineDash != HwmfLineDash.SOLID && dashOffset != null && dashOffset == 0);
+            boolean isGeometric = (unitType == EmfPlusUnitType.World || unitType == EmfPlusUnitType.Display);
+            HemfPenStyle penStyle = HemfPenStyle.valueOf(cap, lineJoin, lineDash, isAlternate, isGeometric);
+            penStyle.setLineDashes(dashedLineData);
 
-                @Override
-                public boolean isGeometric() {
-                    return (unitType == EmfPlusUnitType.World || unitType == EmfPlusUnitType.Display);
-                }
-            });
+            prop.setPenStyle(penStyle);
         }
 
         @Override
index e28c0d713a679abc55184aad068bc526f61cb76b..e445eeeaca178486c11ad1220eac46d6778cea6c 100644 (file)
@@ -25,17 +25,18 @@ import java.util.function.Supplier;
 import org.apache.poi.util.GenericRecordUtil;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.util.Removal;
 
-/** 
- * Definition of a special kind of property of some text, or its 
- *  paragraph. For these properties, a flag in the "contains" header 
+/**
+ * Definition of a special kind of property of some text, or its
+ *  paragraph. For these properties, a flag in the "contains" header
  *  field tells you the data property family will exist. The value
  *  of the property is itself a mask, encoding several different
  *  (but related) properties
  */
-public abstract class BitMaskTextProp extends TextProp implements Cloneable {
+public abstract class BitMaskTextProp extends TextProp {
     protected static final POILogger logger = POILogFactory.getLogger(BitMaskTextProp.class);
-    
+
     private String[] subPropNames;
        private int[] subPropMasks;
        private boolean[] subPropMatches;
@@ -45,20 +46,33 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
        /** Fetch the list of if the sub properties match or not */
        public boolean[] getSubPropMatches() { return subPropMatches; }
 
+
+       protected BitMaskTextProp(BitMaskTextProp other) {
+               super(other);
+               subPropNames = (other.subPropNames == null) ? null : other.subPropNames.clone();
+               subPropMasks = (other.subPropMasks == null) ? null : other.subPropMasks.clone();
+
+               // The old clone implementation didn't carry over matches, but keep everything else as it was
+               // this is failing unit tests
+               // subPropMatches = (other.subPropMatches == null) ? null : new boolean[other.subPropMatches.length];
+               subPropMatches = (other.subPropMatches == null) ? null : other.subPropMatches.clone();
+       }
+
+
        protected BitMaskTextProp(int sizeOfDataBlock, int maskInHeader, String overallName, String... subPropNames) {
                super(sizeOfDataBlock,maskInHeader,overallName);
                this.subPropNames = subPropNames;
                subPropMasks = new int[subPropNames.length];
                subPropMatches = new boolean[subPropNames.length];
-               
+
                int LSB = Integer.lowestOneBit(maskInHeader);
-               
+
                // Initialise the masks list
                for(int i=0; i<subPropMasks.length; i++) {
                        subPropMasks[i] = (LSB << i);
                }
        }
-       
+
        /**
         * Calculate mask from the subPropMatches.
         */
@@ -68,7 +82,7 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
             * The dataValue can't be taken as a mask, as sometimes certain properties
             * are explicitly set to false, i.e. the mask says the property is defined
             * but in the actually nibble the property is set to false
-            */ 
+            */
            int mask = 0, i = 0;
            for (int subMask : subPropMasks) {
                if (subPropMatches[i++]) mask |= subMask;
@@ -91,7 +105,7 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
        /**
         * Return the text property value.
         * Clears all bits of the value, which are marked as unset.
-        * 
+        *
         * @return the text property value.
         */
        @Override
@@ -108,14 +122,14 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
         }
         return val;
        }
-       
+
        /**
         * Set the value of the text property, and recompute the sub
         * properties based on it, i.e. all unset subvalues will be cleared.
-        * Use {@link #setSubValue(boolean, int)} to explicitly set subvalues to {@code false}. 
+        * Use {@link #setSubValue(boolean, int)} to explicitly set subvalues to {@code false}.
         */
        @Override
-       public void setValue(int val) { 
+       public void setValue(int val) {
                super.setValue(val);
 
                // Figure out the values of the sub properties
@@ -149,7 +163,7 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
                }
            }
        }
-       
+
        /**
         * Fetch the true/false status of the subproperty with the given index
         */
@@ -170,20 +184,24 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
         }
         super.setValue(newVal);
        }
-       
+
        @Override
-       public BitMaskTextProp clone(){
-               BitMaskTextProp newObj = (BitMaskTextProp)super.clone();
-               
-               // Don't carry over matches, but keep everything 
-               //  else as it was
-               newObj.subPropMatches = new boolean[subPropMatches.length];
-               
-               return newObj;
+       @SuppressWarnings("squid:S2975")
+       @Deprecated
+       @Removal(version = "5.0.0")
+       public BitMaskTextProp clone() {
+               return copy();
        }
-       
-    public BitMaskTextProp cloneAll(){
-        return (BitMaskTextProp)super.clone();
+
+       /**
+        * @return an identical copy of this, i.e. also the subPropMatches are copied
+        */
+       public BitMaskTextProp cloneAll(){
+               BitMaskTextProp bmtp = copy();
+               if (subPropMatches != null) {
+                       System.arraycopy(subPropMatches, 0, bmtp.subPropMatches, 0, subPropMatches.length);
+               }
+               return bmtp;
     }
 
        @Override
@@ -193,4 +211,7 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
                        "flags", getBitsAsString(this::getValue, subPropMasks, subPropNames)
                );
        }
+
+       @Override
+       public abstract BitMaskTextProp copy();
 }
\ No newline at end of file
index 021d1c4a8490517c6b412c3fbdc020c6bdf98348..4b7046626e662a6b62509eb397b7d7d182d3693b 100644 (file)
@@ -17,7 +17,7 @@
 
 package org.apache.poi.hslf.model.textproperties;
 
-/** 
+/**
  * Definition for the common character text property bitset, which
  *  handles bold/italic/underline etc.
  */
@@ -43,7 +43,7 @@ public class CharFlagsTextProp extends BitMaskTextProp {
                        "fehint",               // 0x0020  A bit that specifies whether characters originated from double-byte input.
                        "unused2",              // 0x0040  Undefined and MUST be ignored.
                        "kumi",                 // 0x0080  A bit that specifies whether Kumimoji are used for vertical text.
-                       "strikethrough",        // 0x0100  aka "unused3" - sometimes contains the strikethrough flag 
+                       "strikethrough",        // 0x0100  aka "unused3" - sometimes contains the strikethrough flag
                        "emboss",               // 0x0200  A bit that specifies whether the characters are embossed.
             "pp9rt_1",              // 0x0400  An unsigned integer that specifies the run grouping of additional text properties in StyleTextProp9Atom record.
             "pp9rt_2",              // 0x0800
@@ -53,4 +53,13 @@ public class CharFlagsTextProp extends BitMaskTextProp {
             "unused4_2"             // 0x8000  Undefined and MUST be ignored.
                );
        }
+
+       public CharFlagsTextProp(CharFlagsTextProp other) {
+               super(other);
+       }
+
+       @Override
+       public CharFlagsTextProp copy() {
+               return new CharFlagsTextProp(this);
+       }
 }
\ No newline at end of file
index 7c87b5d16a30e9a9ad7c091edb92f751818e55d4..b1bf586199d9c63ab917f7f9bec3bce7cee133e4 100644 (file)
@@ -27,7 +27,7 @@ import org.apache.poi.util.GenericRecordUtil;
  * Definition for the font alignment property.
  */
 public class FontAlignmentProp extends TextProp {
-    public static final String NAME = "fontAlign";
+       public static final String NAME = "fontAlign";
        public static final int BASELINE = 0;
        public static final int TOP = 1;
        public static final int CENTER = 2;
@@ -37,6 +37,10 @@ public class FontAlignmentProp extends TextProp {
                super(2, 0x10000, NAME);
        }
 
+       public FontAlignmentProp(FontAlignmentProp other) {
+               super(other);
+       }
+
        public FontAlign getFontAlign() {
                switch (getValue()) {
                        default:
@@ -59,4 +63,9 @@ public class FontAlignmentProp extends TextProp {
                        "fontAlign", this::getFontAlign
                );
        }
+
+       @Override
+       public FontAlignmentProp copy() {
+               return new FontAlignmentProp(this);
+       }
 }
\ No newline at end of file
index 5f747c109fdbe2b3bdf0c6bf6630507737d32070..deb6d67ab7870302a893e2a5c18dc753ed0ce4c9 100644 (file)
@@ -20,21 +20,23 @@ package org.apache.poi.hslf.model.textproperties;
 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.sl.usermodel.TabStop;
 import org.apache.poi.util.GenericRecordUtil;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
 import org.apache.poi.util.Units;
 
 @Internal
-public class HSLFTabStop implements TabStop, Cloneable, GenericRecord {
+public class HSLFTabStop implements TabStop, Duplicatable, GenericRecord {
     /**
      * A signed integer that specifies an offset, in master units, of the tab stop.
-     * 
+     *
      * If the TextPFException record that contains this TabStop structure also contains a
      * leftMargin, then the value of position is relative to the left margin of the paragraph;
      * otherwise, the value is relative to the left side of the paragraph.
-     * 
+     *
      * If a TextRuler record contains this TabStop structure, the value is relative to the
      * left side of the text ruler.
      */
@@ -50,14 +52,19 @@ public class HSLFTabStop implements TabStop, Cloneable, GenericRecord {
         this.type = type;
     }
 
+    public HSLFTabStop(HSLFTabStop other) {
+        position = other.position;
+        type = other.type;
+    }
+
     public int getPosition() {
         return position;
     }
-    
+
     public void setPosition(final int position) {
         this.position = position;
     }
-    
+
     @Override
     public double getPositionInPoints() {
         return Units.masterToPoints(getPosition());
@@ -79,14 +86,18 @@ public class HSLFTabStop implements TabStop, Cloneable, GenericRecord {
     }
 
     @Override
+    @SuppressWarnings("squid:S2975")
+    @Deprecated
+    @Removal(version = "5.0.0")
     public HSLFTabStop clone() {
-        try {
-            return (HSLFTabStop)super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new IllegalStateException(e);
-        }
+        return copy();
     }
-    
+
+    @Override
+    public HSLFTabStop copy() {
+        return new HSLFTabStop(this);
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
index 92b6abbf8128f85792b5980d9248c57e7895686a..abafe05db6df732be3d8514ec894956dd90c7b79 100644 (file)
@@ -31,6 +31,7 @@ import org.apache.poi.util.LittleEndianConsts;
 import org.apache.poi.util.LittleEndianInput;
 import org.apache.poi.util.LittleEndianOutput;
 import org.apache.poi.util.LittleEndianOutputStream;
+import org.apache.poi.util.Removal;
 
 /**
  * Container for tabstop lists
@@ -38,20 +39,18 @@ import org.apache.poi.util.LittleEndianOutputStream;
 @Internal
 public class HSLFTabStopPropCollection extends TextProp {
     public static final String NAME = "tabStops";
-    
+
     private final List<HSLFTabStop> tabStops = new ArrayList<>();
-    
+
     public HSLFTabStopPropCollection() {
         super(0, 0x100000, NAME);
     }
-    
-    public HSLFTabStopPropCollection(final HSLFTabStopPropCollection copy) {
-        super(0, copy.getMask(), copy.getName());
-        for (HSLFTabStop ts : copy.tabStops) {
-            tabStops.add(ts.clone());
-        }
+
+    public HSLFTabStopPropCollection(final HSLFTabStopPropCollection other) {
+        super(other);
+        other.tabStops.stream().map(HSLFTabStop::copy).forEach(tabStops::add);
     }
-    
+
     /**
      * Parses the tabstops from TxMasterStyle record
      *
@@ -61,7 +60,7 @@ public class HSLFTabStopPropCollection extends TextProp {
     public void parseProperty(byte[] data, int offset) {
         tabStops.addAll(readTabStops(new LittleEndianByteArrayInputStream(data, offset)));
     }
-    
+
     public static List<HSLFTabStop> readTabStops(final LittleEndianInput lei) {
         final int count = lei.readUShort();
         final List<HSLFTabStop> tabs = new ArrayList<>(count);
@@ -72,7 +71,7 @@ public class HSLFTabStopPropCollection extends TextProp {
         }
         return tabs;
     }
-    
+
 
     public void writeProperty(OutputStream out) {
         writeTabStops(new LittleEndianOutputStream(out), tabStops);
@@ -85,18 +84,18 @@ public class HSLFTabStopPropCollection extends TextProp {
             leo.writeShort(ts.getPosition());
             leo.writeShort(ts.getType().nativeId);
         }
-        
+
     }
-    
+
     @Override
     public int getValue() { return tabStops.size(); }
 
-    
+
     @Override
     public int getSize() {
         return LittleEndianConsts.SHORT_SIZE + tabStops.size()*LittleEndianConsts.INT_SIZE;
     }
-    
+
     public List<HSLFTabStop> getTabStops() {
         return tabStops;
     }
@@ -104,13 +103,21 @@ public class HSLFTabStopPropCollection extends TextProp {
     public void clearTabs() {
         tabStops.clear();
     }
-    
+
     public void addTabStop(HSLFTabStop ts) {
         tabStops.add(ts);
     }
-    
+
     @Override
+    @SuppressWarnings("squid:S2975")
+    @Deprecated
+    @Removal(version = "5.0.0")
     public HSLFTabStopPropCollection clone() {
+        return copy();
+    }
+
+    @Override
+    public HSLFTabStopPropCollection copy() {
         return new HSLFTabStopPropCollection(this);
     }
 
@@ -134,7 +141,7 @@ public class HSLFTabStopPropCollection extends TextProp {
 
         return tabStops.equals(other.tabStops);
     }
-    
+
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder(super.toString());
@@ -150,7 +157,7 @@ public class HSLFTabStopPropCollection extends TextProp {
             isFirst = false;
         }
         sb.append(" ]");
-        
+
         return sb.toString();
     }
 
index d7c6072eed24c954a9486454622026d2c2aad350..0ffc38e5b3a2c73343e6379ada28742f7097840c 100644 (file)
@@ -38,4 +38,13 @@ public final class ParagraphFlagsTextProp extends BitMaskTextProp {
             "bullet.hardsize"
                );
        }
+
+       public ParagraphFlagsTextProp(ParagraphFlagsTextProp other) {
+               super(other);
+       }
+
+       @Override
+       public ParagraphFlagsTextProp copy() {
+               return new ParagraphFlagsTextProp(this);
+       }
 }
index 62fc80cf0ee56146cca0c0e7fe094a4770b6db11..96c0694208f2cd364174a2f55a820b05725f1fa1 100644 (file)
@@ -32,35 +32,35 @@ public class TextAlignmentProp extends TextProp {
         * For vertical text, top aligned.
         */
     public static final int LEFT = 0;
-    
+
     /**
      * For horizontal text, centered.
      * For vertical text, middle aligned.
      */
        public static final int CENTER = 1;
-       
+
        /**
         * For horizontal text, right aligned.
         * For vertical text, bottom aligned.
         */
        public static final int RIGHT = 2;
-       
+
        /**
         * For horizontal text, flush left and right.
         * For vertical text, flush top and bottom.
         */
        public static final int JUSTIFY = 3;
-       
+
        /**
         * Distribute space between characters.
         */
        public static final int DISTRIBUTED = 4;
-       
+
        /**
         * Thai distribution justification.
         */
        public static final int THAIDISTRIBUTED = 5;
-       
+
        /**
         * Kashida justify low.
         */
@@ -70,6 +70,11 @@ public class TextAlignmentProp extends TextProp {
                super(2, 0x800, "alignment");
        }
 
+
+       public TextAlignmentProp(TextAlignmentProp other) {
+               super(other);
+       }
+
        public TextAlign getTextAlign() {
                switch (getValue()) {
                        default:
@@ -95,4 +100,9 @@ public class TextAlignmentProp extends TextProp {
                        "textAlign", this::getTextAlign
                );
        }
+
+       @Override
+       public TextAlignmentProp copy() {
+               return new TextAlignmentProp(this);
+       }
 }
\ No newline at end of file
index 4dd8b52c096c539e46277fe988245a1b01a7ac9c..8ba72c5c74a938e6eb8a9106d055f80002343c03 100644 (file)
@@ -19,29 +19,32 @@ package org.apache.poi.hslf.model.textproperties;
 
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.function.Supplier;
 
+import org.apache.poi.common.Duplicatable;
 import org.apache.poi.common.usermodel.GenericRecord;
 import org.apache.poi.util.GenericRecordUtil;
+import org.apache.poi.util.Removal;
 
-/** 
- * Definition of a property of some text, or its paragraph. Defines 
- * how to find out if it's present (via the mask on the paragraph or 
- * character "contains" header field), how long the value of it is, 
+/**
+ * Definition of a property of some text, or its paragraph. Defines
+ * how to find out if it's present (via the mask on the paragraph or
+ * character "contains" header field), how long the value of it is,
  * and how to get and set the value.
- * 
+ *
  * As the exact form of these (such as mask value, size of data
  *  block etc) is different for StyleTextProps and
  *  TxMasterTextProps, the definitions of the standard
- *  TextProps is stored in the different record classes 
+ *  TextProps is stored in the different record classes
  */
-public class TextProp implements Cloneable, GenericRecord {
+public class TextProp implements Duplicatable, GenericRecord {
        private int sizeOfDataBlock; // Number of bytes the data part uses
        private String propName;
        private int dataValue;
        private int maskInHeader;
 
-       /** 
+       /**
         * Generate the definition of a given type of text property.
         */
        public TextProp(int sizeOfDataBlock, int maskInHeader, String propName) {
@@ -60,7 +63,7 @@ public class TextProp implements Cloneable, GenericRecord {
            this.propName = other.propName;
            this.dataValue = other.dataValue;
        }
-       
+
        /**
         * Name of the text property
         */
@@ -78,7 +81,7 @@ public class TextProp implements Cloneable, GenericRecord {
        public int getMask() { return maskInHeader; }
        /**
         * Get the mask that's used at write time. Only differs from
-        *  the result of getMask() for the mask based properties 
+        *  the result of getMask() for the mask based properties
         */
        public int getWriteMask() { return getMask(); }
 
@@ -93,27 +96,27 @@ public class TextProp implements Cloneable, GenericRecord {
         */
        public void setValue(int val) { dataValue = val; }
 
+       @Override
+       @SuppressWarnings("squid:S2975")
+       @Deprecated
+       @Removal(version = "5.0.0")
+       public TextProp clone() {
+               return copy();
+       }
+
        /**
         * Clone, eg when you want to actually make use of one of these.
         */
        @Override
-       public TextProp clone(){
-               try {
-                       return (TextProp)super.clone();
-               } catch(CloneNotSupportedException e) {
-                       throw new IllegalStateException(e);
-               }
+       public TextProp copy(){
+               // subclasses need to override copy()
+               assert(TextProp.class.equals(this.getClass()));
+               return new TextProp(this);
        }
-       
+
        @Override
        public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + dataValue;
-        result = prime * result + maskInHeader;
-        result = prime * result + ((propName == null) ? 0 : propName.hashCode());
-        result = prime * result + sizeOfDataBlock;
-        return result;
+               return Objects.hash(dataValue, maskInHeader, propName, sizeOfDataBlock);
     }
 
        @Override
@@ -146,7 +149,7 @@ public class TextProp implements Cloneable, GenericRecord {
         }
         return true;
     }
-    
+
     @Override
     public String toString() {
         int len;
index d564241e11872f83ab4ea7412d236886e4620ff1..8f33257552451895852105a683e9981153e8fe57 100644 (file)
@@ -28,6 +28,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.hslf.exceptions.HSLFException;
 import org.apache.poi.hslf.record.StyleTextPropAtom;
@@ -42,9 +43,9 @@ import org.apache.poi.util.POILogger;
  * Used to hold the number of characters affected, the list of active
  *  properties, and the indent level if required.
  */
-public class TextPropCollection implements GenericRecord {
+public class TextPropCollection implements GenericRecord, Duplicatable {
     private static final POILogger LOG = POILogFactory.getLogger(TextPropCollection.class);
-    
+
     /** All the different kinds of paragraph properties we might handle */
     private static final TextProp[] paragraphTextPropTypes = {
         // TextProp order is according to 2.9.20 TextPFException,
@@ -72,7 +73,7 @@ public class TextPropCollection implements GenericRecord {
         new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size
         // 0xFC000000 MUST be zero and MUST be ignored
     };
-    
+
     /** All the different kinds of character properties we might handle */
     private static final TextProp[] characterTextPropTypes = new TextProp[] {
         new TextProp(0, 0x100000, "pp10ext"),
@@ -92,16 +93,16 @@ public class TextPropCollection implements GenericRecord {
     public enum TextPropType {
         paragraph, character
     }
-    
+
     private int charactersCovered;
-       
+
     // indentLevel is only valid for paragraph collection
     // if it's set to -1, it must be omitted - see 2.9.36 TextMasterStyleLevel
     private short indentLevel;
        private final Map<String,TextProp> textProps = new HashMap<>();
     private int maskSpecial;
     private final TextPropType textPropType;
-    
+
     /**
      * Create a new collection of text properties (be they paragraph
      *  or character) which will be groked via a subsequent call to
@@ -112,6 +113,14 @@ public class TextPropCollection implements GenericRecord {
         this.textPropType = textPropType;
     }
 
+    public TextPropCollection(TextPropCollection other) {
+        charactersCovered = other.charactersCovered;
+        indentLevel = other.indentLevel;
+        maskSpecial = other.maskSpecial;
+        textPropType = other.textPropType;
+        other.textProps.forEach((k,v) -> textProps.put(k, v.copy()));
+    }
+
     public int getSpecialMask() {
         return maskSpecial;
     }
@@ -132,7 +141,7 @@ public class TextPropCollection implements GenericRecord {
         }
            return orderedList;
     }
-       
+
        /** Fetch the TextProp with this name, or null if it isn't present */
        @SuppressWarnings("unchecked")
     public final <T extends TextProp> T findByName(String textPropName) {
@@ -143,18 +152,18 @@ public class TextPropCollection implements GenericRecord {
        public final <T extends TextProp> T removeByName(String name) {
            return (T)textProps.remove(name);
        }
-       
+
        public final TextPropType getTextPropType() {
            return textPropType;
        }
-       
+
        private TextProp[] getPotentialProperties() {
            return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes;
        }
 
        /**
         * Checks the paragraph or character properties for the given property name.
-        * Throws a HSLFException, if the name doesn't belong into this set of properties 
+        * Throws a HSLFException, if the name doesn't belong into this set of properties
         *
         * @param name the property name
         * @return if found, the property template to copy from
@@ -166,21 +175,21 @@ public class TextPropCollection implements GenericRecord {
                 return (T)tp;
             }
         }
-       String errStr = 
+       String errStr =
            "No TextProp with name " + name + " is defined to add from. " +
            "Character and paragraphs have their own properties/names.";
-       throw new HSLFException(errStr);       
+       throw new HSLFException(errStr);
        }
-       
+
     /** Add the TextProp with this name to the list */
     @SuppressWarnings("unchecked")
     public final <T extends TextProp> T addWithName(final String name) {
         // Find the base TextProp to base on
         T existing = findByName(name);
         if (existing != null) return existing;
-        
+
         // Add a copy of this property
-        T textProp = (T)validatePropName(name).clone();
+        T textProp = (T)validatePropName(name).copy();
         textProps.put(name,textProp);
         return textProp;
     }
@@ -197,12 +206,12 @@ public class TextPropCollection implements GenericRecord {
 
            String propName = textProp.getName();
            validatePropName(propName);
-           
+
            textProps.put(propName, textProp);
        }
 
        /**
-        * For an existing set of text properties, build the list of 
+        * For an existing set of text properties, build the list of
         *  properties coded for in a given run of properties.
         * @return the number of bytes that were used encoding the properties list
         */
@@ -224,7 +233,7 @@ public class TextPropCollection implements GenericRecord {
                 }
 
                                // Bingo, data contains this property
-                               TextProp prop = tp.clone();
+                               TextProp prop = tp.copy();
                                int val = 0;
                                if (prop instanceof HSLFTabStopPropCollection) {
                     ((HSLFTabStopPropCollection)prop).parseProperty(data, dataOffset+bytesPassed);
@@ -237,7 +246,7 @@ public class TextPropCollection implements GenericRecord {
                     maskSpecial |= tp.getMask();
                     continue;
                 }
-                               
+
                                if (prop instanceof BitMaskTextProp) {
                                    ((BitMaskTextProp)prop).setValueWithMask(val, containsField);
                                } else if (!(prop instanceof HSLFTabStopPropCollection)) {
@@ -255,26 +264,14 @@ public class TextPropCollection implements GenericRecord {
     /**
      * Clones the given text properties
      */
-       public void copy(TextPropCollection other) {
-           if (other == null) {
-               throw new HSLFException("trying to copy null TextPropCollection");
-           }
-           if (this == other) return;
-        this.charactersCovered = other.charactersCovered;
-        this.indentLevel = other.indentLevel;
-        this.maskSpecial = other.maskSpecial;
-        this.textProps.clear();
-        for (TextProp tp : other.textProps.values()) {
-            TextProp tpCopy = (tp instanceof BitMaskTextProp)
-                ? ((BitMaskTextProp)tp).cloneAll()
-                : tp.clone();
-            addProp(tpCopy);
-        }
+    @Override
+       public TextPropCollection copy() {
+        return new TextPropCollection(this);
        }
-       
+
        /**
         * Update the size of the text that this set of properties
-        *  applies to 
+        *  applies to
         */
        public void updateTextSize(int textSize) {
                charactersCovered = textSize;
@@ -286,7 +283,7 @@ public class TextPropCollection implements GenericRecord {
     public void writeOut(OutputStream o) throws IOException {
         writeOut(o, false);
     }
-       
+
        /**
         * Writes out to disk the header, and then all the properties
         */
@@ -335,7 +332,7 @@ public class TextPropCollection implements GenericRecord {
         }
         this.indentLevel = indentLevel;
     }
-    
+
     public int hashCode() {
         final int prime = 31;
         int result = 1;
@@ -352,7 +349,7 @@ public class TextPropCollection implements GenericRecord {
         if (this == other) return true;
         if (other == null) return false;
         if (getClass() != other.getClass()) return false;
-        
+
         TextPropCollection o = (TextPropCollection)other;
         if (o.maskSpecial != this.maskSpecial || o.indentLevel != this.indentLevel) {
             return false;
@@ -394,7 +391,7 @@ public class TextPropCollection implements GenericRecord {
         } catch (IOException e ) {
             LOG.log(POILogger.ERROR, "can't dump TextPropCollection", e);
         }
-        
+
         return out.toString();
     }
 
index 88e88a82e565be623388780fea49531a417c97bf..27d0d5d9e446c2a5a5ad2afa9d097e77d8335b5e 100644 (file)
@@ -21,10 +21,19 @@ public class WrapFlagsTextProp extends BitMaskTextProp {
     public static final int CHAR_WRAP_IDX = 0;
     public static final int WORD_WRAO_IDX = 1;
     public static final int OVERFLOW_IDX = 2;
-    
+
     public static final String NAME = "wrapFlags";
-    
+
     public WrapFlagsTextProp() {
         super(2, 0xE0000, NAME, "charWrap", "wordWrap", "overflow");
     }
+
+    public WrapFlagsTextProp(WrapFlagsTextProp other) {
+        super(other);
+    }
+
+    @Override
+    public WrapFlagsTextProp copy() {
+        return new WrapFlagsTextProp(this);
+    }
 }
index c0d13c0e64f484f9bad0ae47294e802311e33ff2..0d2a23ba607e562e748e3927c936d1f001c092e5 100644 (file)
@@ -212,13 +212,13 @@ public final class StyleTextPropAtom extends RecordAtom {
         if (initialised) {
             return;
         }
-        
+
         int pos = 0;
         int textHandled = 0;
 
         paragraphStyles.clear();
         charStyles.clear();
-        
+
         // While we have text in need of paragraph stylings, go ahead and
         // grok the contents as paragraph formatting data
         int prsize = size;
@@ -295,10 +295,10 @@ public final class StyleTextPropAtom extends RecordAtom {
 
         initialised = true;
     }
-    
+
     private int checkTextLength(int readLength, int handledSoFar, int overallSize) {
         if (readLength + handledSoFar > overallSize + 1) {
-            logger.log(POILogger.WARN, "Style length of " + readLength + " at " + handledSoFar + 
+            logger.log(POILogger.WARN, "Style length of " + readLength + " at " + handledSoFar +
                     " larger than stated size of " + overallSize + ", truncating");
             return overallSize + 1 - handledSoFar;
         }
@@ -315,20 +315,20 @@ public final class StyleTextPropAtom extends RecordAtom {
             // changed
 
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    
+
             // First up, we need to serialise the paragraph properties
             for(TextPropCollection tpc : paragraphStyles) {
                 tpc.writeOut(baos);
             }
-    
+
             // Now, we do the character ones
             for(TextPropCollection tpc : charStyles) {
                 tpc.writeOut(baos);
             }
-    
+
             rawContents = baos.toByteArray();
         }
-        
+
         // Now ensure that the header size is correct
         int newSize = rawContents.length + reserved.length;
         LittleEndian.putInt(_header,4,newSize);
@@ -343,7 +343,7 @@ public final class StyleTextPropAtom extends RecordAtom {
         reserved = new byte[0];
         initialised = true;
     }
-    
+
     /**
      * Create a new Paragraph TextPropCollection, and add it to the list
      * @param charactersCovered The number of characters this TextPropCollection will cover
@@ -354,6 +354,11 @@ public final class StyleTextPropAtom extends RecordAtom {
         paragraphStyles.add(tpc);
         return tpc;
     }
+
+    public void addParagraphTextPropCollection(TextPropCollection tpc) {
+        paragraphStyles.add(tpc);
+    }
+
     /**
      * Create a new Character TextPropCollection, and add it to the list
      * @param charactersCovered The number of characters this TextPropCollection will cover
@@ -365,6 +370,10 @@ public final class StyleTextPropAtom extends RecordAtom {
         return tpc;
     }
 
+    public void addCharacterTextPropCollection(TextPropCollection tpc) {
+        charStyles.add(tpc);
+    }
+
     /* ************************************************************************ */
 
 
@@ -389,7 +398,7 @@ public final class StyleTextPropAtom extends RecordAtom {
             for(TextPropCollection pr : getCharacterStyles()) {
                 out.append(pr);
             }
-            
+
             out.append("Reserved bytes\n");
             out.append( HexDump.dump(reserved, 0, 0) );
         }
index a706d0d33b16910eaa1760cf216397725c863e2c..3fd987188b113f7d9a07d311ae8557308e88c8ca 100644 (file)
@@ -54,7 +54,7 @@ public final class TxMasterStyleAtom extends RecordAtom {
     private static final POILogger LOG = POILogFactory.getLogger(TxMasterStyleAtom.class);
     //arbitrarily selected; may need to increase
     private static final int MAX_RECORD_LENGTH = 100_000;
-    
+
     /**
      * Maximum number of indentation levels allowed in PowerPoint documents
      */
@@ -166,7 +166,7 @@ public final class TxMasterStyleAtom extends RecordAtom {
 
             head = LittleEndian.getInt(_data, pos);
             pos += LittleEndian.INT_SIZE;
-            
+
             pos += prprops.buildTextPropList( head, _data, pos);
             paragraphStyles.add(prprops);
 
@@ -180,37 +180,35 @@ public final class TxMasterStyleAtom extends RecordAtom {
 
     /**
      * Updates the rawdata from the modified paragraph/character styles
-     * 
+     *
      * @since POI 3.14-beta1
      */
     public void updateStyles() {
         int type = getTextType();
-        
+
         try {
             ByteArrayOutputStream bos = new ByteArrayOutputStream();
             LittleEndianOutputStream leos = new LittleEndianOutputStream(bos);
             int levels = paragraphStyles.size();
             leos.writeShort(levels);
-            
-            TextPropCollection prdummy = new TextPropCollection(0, TextPropType.paragraph);
-            TextPropCollection chdummy = new TextPropCollection(0, TextPropType.character);
-            
+
             for (int i=0; i<levels; i++) {
-                prdummy.copy(paragraphStyles.get(i));
-                chdummy.copy(charStyles.get(i));
+                TextPropCollection prdummy = paragraphStyles.get(i).copy();
+                TextPropCollection chdummy = charStyles.get(i).copy();
+
                 if (type >= TextPlaceholder.CENTER_BODY.nativeId) {
                     leos.writeShort(prdummy.getIndentLevel());
                 }
-                
+
                 // Indent level is not written for master styles
                 prdummy.setIndentLevel((short)-1);
                 prdummy.writeOut(bos, true);
                 chdummy.writeOut(bos, true);
             }
-            
+
             _data = bos.toByteArray();
             leos.close();
-            
+
             LittleEndian.putInt(_header, 4, _data.length);
         } catch (IOException e) {
             throw new HSLFException("error in updating master style properties", e);
index c46881d8fc8b7140b8885ff3ff1c09b597814976..b6e6298cd75b248e5d1a6b8c0267b119203a3b69 100644 (file)
@@ -78,7 +78,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
     private final TextHeaderAtom _headerAtom;
     private TextBytesAtom _byteAtom;
     private TextCharsAtom _charAtom;
-    private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
+    private TextPropCollection _paragraphStyle;
 
     protected TextRulerAtom _ruler;
     protected final List<HSLFTextRun> _runs = new ArrayList<>();
@@ -141,6 +141,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
         _byteAtom = tba;
         _charAtom = tca;
         this.parentList = parentList;
+        _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
     }
 
     /* package */HSLFTextParagraph(HSLFTextParagraph other) {
@@ -151,7 +152,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
         _sheet = other._sheet;
         _ruler = other._ruler;
         shapeId = other.shapeId;
-        _paragraphStyle.copy(other._paragraphStyle);
+        _paragraphStyle = other._paragraphStyle;
         parentList = other.parentList;
     }
 
@@ -169,7 +170,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
     }
 
     public void setParagraphStyle(TextPropCollection paragraphStyle) {
-        _paragraphStyle.copy(paragraphStyle);
+        _paragraphStyle = paragraphStyle;
     }
 
     /**
@@ -906,8 +907,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
 
     /**
      * Check and add linebreaks to text runs leading other paragraphs
-     *
-     * @param paragraphs
      */
     protected static void fixLineEndings(List<HSLFTextParagraph> paragraphs) {
         HSLFTextRun lastRun = null;
@@ -990,7 +989,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
         StyleTextPropAtom styleAtom = findStyleAtomPresent(headerAtom, rawText.length());
 
         // Store in the appropriate record
-        Record oldRecord = null, newRecord = null;
+        Record oldRecord = null, newRecord;
         if (isUnicode) {
             if (byteAtom != null || charAtom == null) {
                 oldRecord = byteAtom;
@@ -1069,15 +1068,17 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
             ptpc = para.getParagraphStyle();
             ptpc.updateTextSize(0);
             if (!ptpc.equals(lastPTPC)) {
-                lastPTPC = styleAtom.addParagraphTextPropCollection(0);
-                lastPTPC.copy(ptpc);
+                lastPTPC = ptpc.copy();
+                lastPTPC.updateTextSize(0);
+                styleAtom.addParagraphTextPropCollection(lastPTPC);
             }
             for (HSLFTextRun tr : para.getTextRuns()) {
                 rtpc = tr.getCharacterStyle();
                 rtpc.updateTextSize(0);
                 if (!rtpc.equals(lastRTPC)) {
-                    lastRTPC = styleAtom.addCharacterTextPropCollection(0);
-                    lastRTPC.copy(rtpc);
+                    lastRTPC = rtpc.copy();
+                    lastRTPC.updateTextSize(0);
+                    styleAtom.addCharacterTextPropCollection(lastRTPC);
                 }
                 int len = tr.getLength();
                 ptpc.updateTextSize(ptpc.getCharactersCovered() + len);
@@ -1096,10 +1097,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
         lastPTPC.updateTextSize(lastPTPC.getCharactersCovered() + 1);
         lastRTPC.updateTextSize(lastRTPC.getCharactersCovered() + 1);
 
-        /**
-         * If TextSpecInfoAtom is present, we must update the text size in it,
-         * otherwise the ppt will be corrupted
-         */
+        // If TextSpecInfoAtom is present, we must update the text size in it,
+        // otherwise the ppt will be corrupted
         for (Record r : paragraphs.get(0).getRecords()) {
             if (r instanceof TextSpecInfoAtom) {
                 ((TextSpecInfoAtom) r).setParentSize(rawText.length() + 1);
@@ -1188,7 +1187,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
                 TextPropCollection tpc = htp.getParagraphStyle();
                 HSLFTextParagraph prevHtp = htp;
                 htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, paragraphs);
-                htp.getParagraphStyle().copy(tpc);
+                htp.setParagraphStyle(tpc.copy());
                 htp.setParentShape(prevHtp.getParentShape());
                 htp.setShapeId(prevHtp.getShapeId());
                 htp.supplySheet(prevHtp.getSheet());
@@ -1199,7 +1198,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
             if (!lastRunEmpty) {
                 TextPropCollection tpc = htr.getCharacterStyle();
                 htr = new HSLFTextRun(htp);
-                htr.getCharacterStyle().copy(tpc);
+                htr.setCharacterStyle(tpc.copy());
                 htp.addTextRun(htr);
             }
             htr.setText(rawText);
@@ -1581,8 +1580,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
                     return;
                 }
                 HSLFTextParagraph htp = paragraphs.get(paraIdx);
-                TextPropCollection pCopy = new TextPropCollection(0, TextPropType.paragraph);
-                pCopy.copy(p);
+                TextPropCollection pCopy = p.copy();
                 htp.setParagraphStyle(pCopy);
                 int len = 0;
                 for (HSLFTextRun trun : htp.getTextRuns()) {
index 94cea55ab2aab08d2ec8e03171855871876d772b..144fa33950c0c2b3473326373ac40a67c4e4c3ab 100644 (file)
@@ -74,7 +74,7 @@ public final class HSLFTextRun implements TextRun {
        }
 
        public void setCharacterStyle(TextPropCollection characterStyle) {
-           this.characterStyle.copy(characterStyle);
+           this.characterStyle = characterStyle.copy();
            this.characterStyle.updateTextSize(_runText.length());
        }
 
@@ -150,7 +150,7 @@ public final class HSLFTextRun implements TextRun {
             logger.log(POILogger.ERROR, "Sheet is not available");
             return null;
         }
-        
+
         final HSLFMasterSheet master = sheet.getMasterSheet();
         if (master == null) {
             logger.log(POILogger.WARN, "MasterSheet is not available");
@@ -161,8 +161,8 @@ public final class HSLFTextRun implements TextRun {
         final TextPropCollection col = master.getPropCollection(txtype, parentParagraph.getIndentLevel(), name, true);
         return (col == null) ? null : col.findByName(name);
        }
-       
-       
+
+
        /**
         * Set the value of the given flag in the CharFlagsTextProp, adding
         *  it if required.
@@ -315,7 +315,7 @@ public final class HSLFTextRun implements TextRun {
     @Override
        public void setFontInfo(FontInfo fontInfo, FontGroup fontGroup) {
         FontGroup fg = safeFontGroup(fontGroup);
-        
+
         HSLFSheet sheet = parentParagraph.getSheet();
         @SuppressWarnings("resource")
         HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
@@ -520,7 +520,7 @@ public final class HSLFTextRun implements TextRun {
 
         return null;
     }
-    
+
     private FontGroup safeFontGroup(FontGroup fontGroup) {
         return (fontGroup != null) ? fontGroup : FontGroup.getFontGroupFirst(getRawText());
     }
index 6e1e72ddb8d2c3cd1de20afb9a9750ff5b1e5e26..dd57be2c88462fe6ec5dee324e739a1e2032adb4 100644 (file)
@@ -97,21 +97,21 @@ public class HwmfDrawProperties {
         font = new HwmfFont();
         font.initDefaults();
     }
-    
+
     public HwmfDrawProperties(HwmfDrawProperties other) {
         this.window = (other.window == null) ? null : (Rectangle2D)other.window.clone();
         this.viewport = (other.viewport == null) ? null : (Rectangle2D)other.viewport.clone();
         this.location = (Point2D)other.location.clone();
         this.mapMode = other.mapMode;
-        this.backgroundColor = (other.backgroundColor == null) ? null : other.backgroundColor.clone();
+        this.backgroundColor = (other.backgroundColor == null) ? null : other.backgroundColor.copy();
         this.brushStyle = other.brushStyle;
-        this.brushColor = other.brushColor.clone();
+        this.brushColor = other.brushColor.copy();
         this.brushHatch = other.brushHatch;
         this.brushBitmap = other.brushBitmap;
         this.brushTransform.setTransform(other.brushTransform);
         this.penWidth = other.penWidth;
-        this.penStyle = (other.penStyle == null) ? null : other.penStyle.clone();
-        this.penColor = (other.penColor == null) ? null : other.penColor.clone();
+        this.penStyle = (other.penStyle == null) ? null : other.penStyle.copy();
+        this.penColor = (other.penColor == null) ? null : other.penColor.copy();
         this.penMiterLimit = other.penMiterLimit;
         this.bkMode = other.bkMode;
         this.polyfillMode = other.polyfillMode;
@@ -123,7 +123,7 @@ public class HwmfDrawProperties {
         this.palette = other.palette;
         this.paletteOffset = other.paletteOffset;
         this.font = other.font;
-        this.textColor = (other.textColor == null) ? null : other.textColor.clone();
+        this.textColor = (other.textColor == null) ? null : other.textColor.copy();
         this.textAlignLatin = other.textAlignLatin;
         this.textVAlignLatin = other.textVAlignLatin;
         this.textAlignAsian = other.textAlignAsian;
@@ -132,7 +132,7 @@ public class HwmfDrawProperties {
         this.transform.setTransform(other.transform);
         this.clip = other.clip;
     }
-    
+
     public void setViewportExt(double width, double height) {
         if (viewport == null) {
             viewport = (Rectangle2D)window.clone();
@@ -308,7 +308,7 @@ public class HwmfDrawProperties {
     /**
      * Returns the current palette.
      * Callers may modify the palette.
-     * 
+     *
      * @return the current palette or null, if it hasn't been set
      */
     public List<PaletteEntry> getPalette() {
index 1ea80968a30879be943fe9bd35172d8a457aaedd..6cb4c41def77d0535b7962145dda7cce52e797c7 100644 (file)
@@ -22,6 +22,7 @@ import java.io.IOException;
 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.GenericRecordJsonWriter;
 import org.apache.poi.util.GenericRecordUtil;
@@ -35,15 +36,19 @@ import org.apache.poi.util.LittleEndianInputStream;
  * Blue (1 byte):  An 8-bit unsigned integer that defines the relative intensity of blue.
  * Reserved (1 byte):  An 8-bit unsigned integer that MUST be 0x00.
  */
-public class HwmfColorRef implements Cloneable, GenericRecord {
+public class HwmfColorRef implements Duplicatable, GenericRecord {
     private Color colorRef = Color.BLACK;
-    
+
     public HwmfColorRef() {}
-    
+
+    public HwmfColorRef(HwmfColorRef other) {
+        colorRef = other.colorRef;
+    }
+
     public HwmfColorRef(Color colorRef) {
         this.colorRef = colorRef;
     }
-    
+
     public int init(LittleEndianInputStream leis) throws IOException {
         int red = leis.readUByte();
         int green = leis.readUByte();
@@ -62,21 +67,9 @@ public class HwmfColorRef implements Cloneable, GenericRecord {
         colorRef = color;
     }
 
-    /**
-     * Creates a new object of the same class and with the
-     * same contents as this object.
-     * @return     a clone of this instance.
-     * @exception  OutOfMemoryError            if there is not enough memory.
-     * @see        java.lang.Cloneable
-     */
     @Override
-    public HwmfColorRef clone() {
-        try {
-            return (HwmfColorRef)super.clone();
-        } catch (CloneNotSupportedException e) {
-            // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
-        }
+    public HwmfColorRef copy() {
+        return new HwmfColorRef(this);
     }
 
     @Override
index 261b60a439fe96ff6a12420a6009b60555b4cfea..5976322e90fb61215675855c554c74a7cdd01e35 100644 (file)
@@ -21,6 +21,7 @@ import java.awt.BasicStroke;
 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;
@@ -30,21 +31,21 @@ import org.apache.poi.util.GenericRecordUtil;
 /**
  * The 16-bit PenStyle Enumeration is used to specify different types of pens
  * that can be used in graphics operations.
- * 
+ *
  * Various styles can be combined by using a logical OR statement, one from
  * each subsection of Style, EndCap, Join, and Type (Cosmetic).
- * 
+ *
  * The defaults in case the other values of the subsection aren't set are
  * solid, round end caps, round joins and cosmetic type.
  */
-public class HwmfPenStyle implements Cloneable, GenericRecord {
+public class HwmfPenStyle implements Duplicatable, GenericRecord {
     public enum HwmfLineCap {
         /** Rounded ends */
         ROUND(0, BasicStroke.CAP_ROUND),
         /** Square protrudes by half line width */
         SQUARE(1, BasicStroke.CAP_SQUARE),
         /** Line ends at end point*/
-        FLAT(2, BasicStroke.CAP_BUTT);        
+        FLAT(2, BasicStroke.CAP_BUTT);
 
         public final int wmfFlag;
         public final int awtFlag;
@@ -58,9 +59,9 @@ public class HwmfPenStyle implements Cloneable, GenericRecord {
                 if (hs.wmfFlag == wmfFlag) return hs;
             }
             return null;
-        }    
+        }
     }
-    
+
     public enum HwmfLineJoin {
         /**Line joins are round. */
         ROUND(0, BasicStroke.JOIN_ROUND),
@@ -84,16 +85,16 @@ public class HwmfPenStyle implements Cloneable, GenericRecord {
                 if (hs.wmfFlag == wmfFlag) return hs;
             }
             return null;
-        }    
+        }
     }
-    
+
     public enum HwmfLineDash {
         /**
          * The pen is solid.
          */
         SOLID(0x0000, null),
         /**
-         * The pen is dashed. (-----) 
+         * The pen is dashed. (-----)
          */
         DASH(0x0001, 10, 8),
         /**
@@ -124,7 +125,7 @@ public class HwmfPenStyle implements Cloneable, GenericRecord {
          * styling is supposed to come from ...)
          */
         USERSTYLE(0x0007, null);
-        
+
 
         public final int wmfFlag;
         public final float[] dashes;
@@ -138,23 +139,29 @@ public class HwmfPenStyle implements Cloneable, GenericRecord {
                 if (hs.wmfFlag == wmfFlag) return hs;
             }
             return null;
-        }    
+        }
     }
-    
-    private static final BitField SUBSECTION_DASH      = BitFieldFactory.getInstance(0x00007);
-    private static final BitField SUBSECTION_ALTERNATE = BitFieldFactory.getInstance(0x00008);
-    private static final BitField SUBSECTION_ENDCAP    = BitFieldFactory.getInstance(0x00300);
-    private static final BitField SUBSECTION_JOIN      = BitFieldFactory.getInstance(0x03000);
-    private static final BitField SUBSECTION_GEOMETRIC = BitFieldFactory.getInstance(0x10000);
+
+    protected static final BitField SUBSECTION_DASH      = BitFieldFactory.getInstance(0x00007);
+    protected static final BitField SUBSECTION_ALTERNATE = BitFieldFactory.getInstance(0x00008);
+    protected static final BitField SUBSECTION_ENDCAP    = BitFieldFactory.getInstance(0x00300);
+    protected static final BitField SUBSECTION_JOIN      = BitFieldFactory.getInstance(0x03000);
+    protected static final BitField SUBSECTION_GEOMETRIC = BitFieldFactory.getInstance(0x10000);
 
     protected int flag;
-    
+
+    public HwmfPenStyle(int flag) {
+        this.flag = flag;
+    }
+
+    public HwmfPenStyle(HwmfPenStyle other) {
+        flag = other.flag;
+    }
+
     public static HwmfPenStyle valueOf(int flag) {
-        HwmfPenStyle ps = new HwmfPenStyle();
-        ps.flag = flag;
-        return ps;
+        return new HwmfPenStyle(flag);
     }
-    
+
     public HwmfLineCap getLineCap() {
         return HwmfLineCap.valueOf(SUBSECTION_ENDCAP.getValue(flag));
     }
@@ -162,7 +169,7 @@ public class HwmfPenStyle implements Cloneable, GenericRecord {
     public HwmfLineJoin getLineJoin() {
         return HwmfLineJoin.valueOf(SUBSECTION_JOIN.getValue(flag));
     }
-    
+
     public HwmfLineDash getLineDash() {
         return HwmfLineDash.valueOf(SUBSECTION_DASH.getValue(flag));
     }
@@ -193,21 +200,9 @@ public class HwmfPenStyle implements Cloneable, GenericRecord {
     }
 
 
-    /**
-     * Creates a new object of the same class and with the
-     * same contents as this object.
-     * @return     a clone of this instance.
-     * @exception  OutOfMemoryError            if there is not enough memory.
-     * @see        java.lang.Cloneable
-     */
     @Override
-    public HwmfPenStyle clone() {
-        try {
-            return (HwmfPenStyle)super.clone();
-        } catch (CloneNotSupportedException e) {
-            // this shouldn't happen, since we are Cloneable
-            throw new InternalError();
-        }
+    public HwmfPenStyle copy() {
+        return new HwmfPenStyle(this);
     }
 
     @Override
index 45819504f61a0980864dc0656b07f64c973b0307..9bc4dfde22446eca01b779fa997794d6b3e003a9 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.hssf.record;
 
 import static org.junit.Assert.assertArrayEquals;
+
 import junit.framework.TestCase;
 
 /**
@@ -57,7 +58,7 @@ public final class TestAutoFilterInfoRecord extends TestCase {
         record.setNumEntries((short)3);
         byte[] src = record.serialize();
 
-        AutoFilterInfoRecord cloned = record.clone();
+        AutoFilterInfoRecord cloned = record.copy();
         assertEquals(3, record.getNumEntries());
         byte[] cln = cloned.serialize();
 
index acaddd0f6b50e33788611fefa7211629eb8b8856..5b99e8c973ab37a3244501030df79db848a72ecd 100644 (file)
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 
+import junit.framework.AssertionFailedError;
 import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator;
 import org.apache.poi.hssf.record.cf.BorderFormatting;
@@ -42,8 +43,6 @@ import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
 import org.apache.poi.util.LittleEndian;
 import org.junit.Test;
 
-import junit.framework.AssertionFailedError;
-
 /**
  * Tests the serialization and deserialization of the TestCFRuleRecord
  * class works correctly.
@@ -141,8 +140,8 @@ public final class TestCFRuleRecord {
         record.getMultiStateFormatting().getThresholds()[1].setValue(10d);
         record.getMultiStateFormatting().getThresholds()[2].setType(RangeType.NUMBER.id);
         record.getMultiStateFormatting().getThresholds()[2].setValue(-4d);
-        
-        // Check it 
+
+        // Check it
         testCFRule12Record(record);
         assertEquals(IconSet.GREY_5_ARROWS, record.getMultiStateFormatting().getIconSet());
         assertEquals(5, record.getMultiStateFormatting().getThresholds().length);
@@ -156,7 +155,7 @@ public final class TestCFRuleRecord {
 
         // Deserialize
         record = new CFRule12Record(TestcaseRecordInputStream.create(CFRule12Record.sid, recordData));
-        
+
         // Check it has the icon, and the right number of thresholds
         assertEquals(IconSet.GREY_5_ARROWS, record.getMultiStateFormatting().getIconSet());
         assertEquals(5, record.getMultiStateFormatting().getThresholds().length);
@@ -172,10 +171,10 @@ public final class TestCFRuleRecord {
         }
         workbook.close();
     }
-    
+
     private void testCFRuleRecord(CFRuleRecord record) {
         testCFRuleBase(record);
-        
+
         assertFalse(record.isLeftBorderModified());
         record.setLeftBorderModified(true);
         assertTrue(record.isLeftBorderModified());
@@ -445,22 +444,22 @@ public final class TestCFRuleRecord {
         byte[] data = rr.serialize();
         TestcaseRecordInputStream.confirmRecordEncoding(CFRuleRecord.sid, DATA_REFN, data);
     }
-    
+
     @Test
     public void testBug53691() throws IOException {
         HSSFWorkbook workbook = new HSSFWorkbook();
         HSSFSheet sheet = workbook.createSheet();
 
         CFRuleRecord record = CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5");
-        
-        CFRuleRecord clone = record.clone();
-        
+
+        CFRuleRecord clone = record.copy();
+
         byte [] serializedRecord = record.serialize();
         byte [] serializedClone = clone.serialize();
         assertArrayEquals(serializedRecord, serializedClone);
         workbook.close();
     }
-    
+
     @Test
     public void testBug57231_rewrite() throws IOException {
         HSSFWorkbook wb1 = HSSFITestDataProvider.instance.openSampleWorkbook("57231_MixedGasReport.xls");
index 38230723482ff358f4bf147bc8a114ac289f3e4a..a4ba179be9e2a459980b3a043621925fc265c204 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
 
 
 import static org.junit.Assert.assertArrayEquals;
+
 import junit.framework.TestCase;
 
 /**
@@ -56,7 +57,7 @@ public final class TestFtCblsSubRecord extends TestCase {
         FtCblsSubRecord record = new FtCblsSubRecord();
         byte[] src = record.serialize();
 
-        FtCblsSubRecord cloned = record.clone();
+        FtCblsSubRecord cloned = record.copy();
         byte[] cln = cloned.serialize();
 
         assertEquals(record.getDataSize(), cloned.getDataSize());
index 2379a29db4a08bd9d8a20d628a550e08f7ad93a5..b2290b1913cdb4de9ea802efebe3379929b50cba 100644 (file)
@@ -34,40 +34,40 @@ import org.junit.Test;
 public final class TestHyperlinkRecord {
 
     //link to http://www.lakings.com/
-    private static final byte[] data1 = { 
+    private static final byte[] data1 = {
         0x02, 0x00,    //First row of the hyperlink
         0x02, 0x00,    //Last row of the hyperlink
         0x00, 0x00,    //First column of the hyperlink
         0x00, 0x00,    //Last column of the hyperlink
-        
+
         //16-byte GUID. Seems to be always the same. Does not depend on the hyperlink type
         (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
         (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
-        
+
         0x02, 0x00, 0x00, 0x00, //integer, always 2
-        
+
         // flags. Define the type of the hyperlink:
         // HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL
         0x17, 0x00, 0x00, 0x00,
-        
+
         0x08, 0x00, 0x00, 0x00, //length of the label including the trailing '\0'
-        
+
         //label:
         0x4D, 0x00, 0x79, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x6B, 0x00, 0x00, 0x00,
-        
+
         //16-byte link moniker: HyperlinkRecord.URL_MONIKER
         (byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE,  0x11,
         (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
-        
+
         //count of bytes in the address including the tail
         0x48, 0x00, 0x00, 0x00, //integer
-        
+
         //the actual link, terminated by '\u0000'
         0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x3A, 0x00, 0x2F, 0x00,
         0x2F, 0x00, 0x77, 0x00, 0x77, 0x00, 0x77, 0x00, 0x2E, 0x00, 0x6C, 0x00,
         0x61, 0x00, 0x6B, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x73, 0x00,
         0x2E, 0x00, 0x63, 0x00, 0x6F, 0x00, 0x6D, 0x00, 0x2F, 0x00, 0x00, 0x00,
-        
+
         //standard 24-byte tail of a URL link. Seems to always be the same for all URL HLINKs
         0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, 0x2C,
         (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00,
@@ -83,29 +83,29 @@ public final class TestHyperlinkRecord {
         //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type
         (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
         (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
-        
+
         0x02, 0x00, 0x00, 0x00,    //integer, always 2
-        
+
         0x15, 0x00, 0x00, 0x00,    //options: HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL
-        
+
         0x05, 0x00, 0x00, 0x00,    //length of the label
         //label
         0x66, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x00, 0x00,
-        
+
         //16-byte link moniker: HyperlinkRecord.FILE_MONIKER
         0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
-        
+
         0x00, 0x00,    //level
         0x0A, 0x00, 0x00, 0x00,    //length of the path )
-        
+
         //path to the file (plain ISO-8859 bytes, NOT UTF-16LE!)
         0x6C, 0x69, 0x6E, 0x6B, 0x31, 0x2E, 0x78, 0x6C, 0x73, 0x00,
-        
+
         //standard 24-byte tail of a file link
         (byte)0xFF, (byte)0xFF, (byte)0xAD, (byte)0xDE, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00,
-        
+
         0x00, 0x00, 0x00, 0x00, // length of address link field
     };
 
@@ -115,25 +115,25 @@ public final class TestHyperlinkRecord {
         0x01, 0x00,
         0x00, 0x00,
         0x00, 0x00,
-        
+
         //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type
         (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
         (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
-        
+
         0x02, 0x00, 0x00, 0x00, //integer, always 2
-        
+
         0x17, 0x00, 0x00, 0x00,  //options: HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL
-        
+
         0x06, 0x00, 0x00, 0x00,     //length of the label
         0x65, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x00, 0x00, //label
-        
+
         //16-byte link moniker: HyperlinkRecord.URL_MONIKER
         (byte)0xE0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
         (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
-        
+
         //length of the address including the tail.
         0x76, 0x00, 0x00, 0x00,
-        
+
         //the address is terminated by '\u0000'
         0x6D, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x74, 0x00, 0x6F, 0x00,
         0x3A, 0x00, 0x65, 0x00, 0x62, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6E, 0x00,
@@ -143,7 +143,7 @@ public final class TestHyperlinkRecord {
         0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x2C, 0x00,
         0x25, 0x00, 0x32, 0x00, 0x30, 0x00, 0x45, 0x00, 0x62, 0x00, 0x67, 0x00,
         0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x21, 0x00, 0x00, 0x00,
-        
+
         //standard 24-byte tail of a URL link
         0x79, 0x58, (byte)0x81, (byte)0xF4, 0x3B, 0x1D, 0x7F, 0x48, (byte)0xAF, (byte)0x2C,
         (byte)0x82, 0x5D, (byte)0xC4, (byte)0x85, 0x27, 0x63, 0x00, 0x00, 0x00,
@@ -156,21 +156,21 @@ public final class TestHyperlinkRecord {
         0x03, 0x00,
         0x00, 0x00,
         0x00, 0x00,
-        
+
         //16-bit GUID. Seems to be always the same. Does not depend on the hyperlink type
         (byte)0xD0, (byte)0xC9, (byte)0xEA, 0x79, (byte)0xF9, (byte)0xBA, (byte)0xCE, 0x11,
         (byte)0x8C, (byte)0x82, 0x00, (byte)0xAA, 0x00, 0x4B, (byte)0xA9, 0x0B,
-        
+
         0x02, 0x00, 0x00, 0x00, //integer, always 2
-        
+
         0x1C, 0x00, 0x00, 0x00, //flags: HyperlinkRecord.HLINK_LABEL | HyperlinkRecord.HLINK_PLACE
-        
+
         0x06, 0x00, 0x00, 0x00, //length of the label
-        
+
         0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x00, 0x00, //label
-        
+
         0x0A, 0x00, 0x00, 0x00, //length of the document link including trailing zero
-        
+
         //link: Sheet1!A1
         0x53, 0x00, 0x68, 0x00, 0x65, 0x00, 0x65, 0x00, 0x74, 0x00, 0x31, 0x00, 0x21,
         0x00, 0x41, 0x00, 0x31, 0x00, 0x00, 0x00
@@ -246,7 +246,7 @@ public final class TestHyperlinkRecord {
        "61 00 72 00 65 00 5C 00 6D 00 79 00 44 00 69 00 " +
        "72 00 5C 00 50 00 52 00 4F 00 44 00 4E 00 41 00 " +
        "4D 00 45 00 2E 00 78 00 6C 00 73 00 00 00 " +
-    
+
        "0C 00 00 00 " + // textMark: PRODNAME!C2
        "50 00 52 00 4F 00 44 00 4E 00 41 00 4D 00 45 00 21 00 " +
        "43 00 32 00 00 00"
@@ -274,7 +274,7 @@ public final class TestHyperlinkRecord {
     private void confirmGUID(GUID expectedGuid, GUID actualGuid) {
                assertEquals(expectedGuid, actualGuid);
        }
-    
+
     @Test
     public void testReadURLLink(){
         RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data1);
@@ -442,7 +442,7 @@ public final class TestHyperlinkRecord {
         for (final byte[] d : data) {
             RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, d);
             HyperlinkRecord link = new HyperlinkRecord(is);
-            HyperlinkRecord clone = link.clone();
+            HyperlinkRecord clone = link.copy();
             assertArrayEquals(link.serialize(), clone.serialize());
         }
 
@@ -480,7 +480,7 @@ public final class TestHyperlinkRecord {
                    fail("Identified bug with option URL and UNC set at same time");
                }
        }
-       
+
     @Test
        public void testGUID() {
                GUID g;
index f002aa8ebc8df9bfc93f8e877b289a5c9d83d9e7..4694306d3452351a93547ae6c2fa95a9e7f314cc 100644 (file)
@@ -22,7 +22,6 @@ import java.util.List;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
-
 import org.apache.poi.hssf.model.RecordStream;
 import org.apache.poi.hssf.record.aggregates.MergedCellsTable;
 import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
@@ -35,14 +34,14 @@ import org.apache.poi.ss.util.CellRangeAddress;
  *
  */
 public final class TestMergeCellsRecord extends TestCase {
-   
+
        /**
         * Make sure when a clone is called, we actually clone it.
         */
        public void testCloneReferences() {
                CellRangeAddress[] cras = { new CellRangeAddress(0, 1, 0, 2), };
                MergeCellsRecord merge = new MergeCellsRecord(cras, 0, cras.length);
-               MergeCellsRecord clone = merge.clone();
+               MergeCellsRecord clone = merge.copy();
 
                assertNotSame("Merged and cloned objects are the same", merge, clone);
 
@@ -56,7 +55,7 @@ public final class TestMergeCellsRecord extends TestCase {
 
         assertNotSame(merge.getAreaAt(0), clone.getAreaAt(0));
        }
-   
+
        private static final RecordVisitor dummyRecordVisitor = new RecordVisitor() {
                @Override
         public void visitRecord(Record r) {
@@ -67,7 +66,7 @@ public final class TestMergeCellsRecord extends TestCase {
                MergedCellsTable mct = new MergedCellsTable();
                List<Record> recList = new ArrayList<>();
                CellRangeAddress[] cras = new CellRangeAddress[] {
-                               new CellRangeAddress(0, 0, 0, 3), 
+                               new CellRangeAddress(0, 0, 0, 3),
                };
                recList.add(new MergeCellsRecord(cras, 0, 1));
                RecordStream rs = new RecordStream(recList, 0);
index 5f238f80c718438ea47a354c695e5a26df2fdd06..1f2e37709f310cc87fb5d07c87aea4a899ab59a3 100644 (file)
@@ -18,9 +18,9 @@
 package org.apache.poi.hssf.record;
 
 import static org.junit.Assert.assertArrayEquals;
+
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
-
 import org.apache.poi.util.HexRead;
 
 /**
@@ -53,7 +53,7 @@ public final class TestNoteRecord extends TestCase {
     public void testWrite() {
         NoteRecord record = new NoteRecord();
         assertEquals(NoteRecord.sid, record.getSid());
-        
+
         record.setRow((short)6);
         record.setColumn((short)1);
         record.setFlags(NoteRecord.NOTE_VISIBLE);
@@ -73,7 +73,7 @@ public final class TestNoteRecord extends TestCase {
         record.setShapeId((short)1026);
         record.setAuthor("Apache Software Foundation");
 
-        NoteRecord cloned = record.clone();
+        NoteRecord cloned = record.copy();
         assertEquals(record.getRow(), cloned.getRow());
         assertEquals(record.getColumn(), cloned.getColumn());
         assertEquals(record.getFlags(), cloned.getFlags());
@@ -85,14 +85,14 @@ public final class TestNoteRecord extends TestCase {
         byte[] cln = cloned.serialize();
         assertArrayEquals(src, cln);
     }
-    
+
     public void testUnicodeAuthor() {
-        // This sample data was created by setting the 'user name' field in the 'Personalize' 
-        // section of Excel's options to \u30A2\u30D1\u30C3\u30C1\u65CF, and then 
+        // This sample data was created by setting the 'user name' field in the 'Personalize'
+        // section of Excel's options to \u30A2\u30D1\u30C3\u30C1\u65CF, and then
         // creating a cell comment.
         byte[] data = HexRead.readFromString("01 00 01 00 00 00 03 00 " +
                 "05 00 01 " + // len=5, 16bit
-                "A2 30 D1 30 C3 30 C1 30 CF 65 " + // character data 
+                "A2 30 D1 30 C3 30 C1 30 CF 65 " + // character data
                 "00 " // padding byte
                 );
         RecordInputStream in = TestcaseRecordInputStream.create(NoteRecord.sid, data);
@@ -102,7 +102,7 @@ public final class TestNoteRecord extends TestCase {
         }
         assertEquals("\u30A2\u30D1\u30C3\u30C1\u65CF", nr.getAuthor());
         assertTrue(nr.authorIsMultibyte());
-        
+
         byte[] ser = nr.serialize();
         TestcaseRecordInputStream.confirmRecordEncoding(NoteRecord.sid, data, ser);
 
@@ -111,23 +111,23 @@ public final class TestNoteRecord extends TestCase {
         nr = new NoteRecord(in);
         assertEquals("\u30A2\u30D1\u30C3\u30C1\u65CF", nr.getAuthor());
         assertTrue(nr.authorIsMultibyte());
-        
-        
+
+
         // Change to a non unicode author, will stop being unicode
         nr.setAuthor("Simple");
         ser = nr.serialize();
         in = TestcaseRecordInputStream.create(ser);
         nr = new NoteRecord(in);
-        
+
         assertEquals("Simple", nr.getAuthor());
         assertFalse(nr.authorIsMultibyte());
-        
+
         // Now set it back again
         nr.setAuthor("Unicode\u1234");
         ser = nr.serialize();
         in = TestcaseRecordInputStream.create(ser);
         nr = new NoteRecord(in);
-        
+
         assertEquals("Unicode\u1234", nr.getAuthor());
         assertTrue(nr.authorIsMultibyte());
     }
index 5a4d5c887c66d4f55c5ced7d3d8b10460dc90228..30631243a5f6818bc75c646a8798138c51887618 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
 
 
 import static org.junit.Assert.assertArrayEquals;
+
 import junit.framework.TestCase;
 
 /**
@@ -58,7 +59,7 @@ public final class TestNoteStructureSubRecord extends TestCase {
         NoteStructureSubRecord record = new NoteStructureSubRecord();
         byte[] src = record.serialize();
 
-        NoteStructureSubRecord cloned = record.clone();
+        NoteStructureSubRecord cloned = record.copy();
         byte[] cln = cloned.serialize();
 
         assertEquals(record.getDataSize(), cloned.getDataSize());
index e2b2652a435a0caa9f9686a82fe5a1a3c4034c8d..e024f67af41d9ec457a491fcf3d7c0a9d4971c18 100644 (file)
 package org.apache.poi.hssf.record;
 
 import junit.framework.TestCase;
-
 import org.apache.poi.hssf.record.common.UnicodeString;
 import org.apache.poi.hssf.record.cont.ContinuableRecordOutput;
 import org.apache.poi.util.IntMapper;
+import org.apache.poi.util.LittleEndianConsts;
 
 /**
  * Tests that records size calculates correctly.
- * 
+ *
  * @author Glen Stampoultzis (glens at apache.org)
  */
 public final class TestSSTRecordSizeCalculator extends TestCase {
        private static final String SMALL_STRING = "Small string";
        private static final int COMPRESSED_PLAIN_STRING_OVERHEAD = 3;
        private static final int OPTION_FIELD_SIZE = 1;
-       
+
        private final IntMapper<UnicodeString> strings = new IntMapper<>();
 
+
+       /** standard record overhead: two shorts (record id plus data space size)*/
+       private 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 */
+       private 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 */
+       private static final int MAX_DATA_SPACE = RecordInputStream.MAX_RECORD_DATA_SIZE - 8;
+
+
        private void confirmSize(int expectedSize) {
                ContinuableRecordOutput cro = ContinuableRecordOutput.createForCountingOnly();
                SSTSerializer ss = new SSTSerializer(strings, 0, 0);
@@ -44,64 +55,64 @@ public final class TestSSTRecordSizeCalculator extends TestCase {
 
        public void testBasic() {
                strings.add(makeUnicodeString(SMALL_STRING));
-               confirmSize(SSTRecord.SST_RECORD_OVERHEAD
+               confirmSize(SST_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
                                + SMALL_STRING.length());
        }
 
        public void testBigStringAcrossUnicode() {
-               int bigString = SSTRecord.MAX_DATA_SPACE + 100;
+               int bigString = MAX_DATA_SPACE + 100;
                strings.add(makeUnicodeString(bigString));
-               confirmSize(SSTRecord.SST_RECORD_OVERHEAD
+               confirmSize(SST_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
-                               + SSTRecord.MAX_DATA_SPACE
-                               + SSTRecord.STD_RECORD_OVERHEAD
+                               + MAX_DATA_SPACE
+                               + STD_RECORD_OVERHEAD
                                + OPTION_FIELD_SIZE
                                + 100);
        }
 
        public void testPerfectFit() {
-               int perfectFit = SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD;
+               int perfectFit = MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD;
                strings.add(makeUnicodeString(perfectFit));
-               confirmSize(SSTRecord.SST_RECORD_OVERHEAD
+               confirmSize(SST_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
                                + perfectFit);
        }
 
        public void testJustOversized() {
-               int tooBig = SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD + 1;
+               int tooBig = MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD + 1;
                strings.add(makeUnicodeString(tooBig));
-               confirmSize(SSTRecord.SST_RECORD_OVERHEAD
+               confirmSize(SST_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
                                + tooBig - 1
                                // continue record
-                               + SSTRecord.STD_RECORD_OVERHEAD
+                               + STD_RECORD_OVERHEAD
                                + OPTION_FIELD_SIZE + 1);
 
        }
 
        public void testSecondStringStartsOnNewContinuation() {
-               int perfectFit = SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD;
+               int perfectFit = MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD;
                strings.add(makeUnicodeString(perfectFit));
                strings.add(makeUnicodeString(SMALL_STRING));
-               confirmSize(SSTRecord.SST_RECORD_OVERHEAD
-                               + SSTRecord.MAX_DATA_SPACE
+               confirmSize(SST_RECORD_OVERHEAD
+                               + MAX_DATA_SPACE
                                // second string
-                               + SSTRecord.STD_RECORD_OVERHEAD
+                               + STD_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
                                + SMALL_STRING.length());
        }
 
        public void testHeaderCrossesNormalContinuePoint() {
-               int almostPerfectFit = SSTRecord.MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD - 2;
+               int almostPerfectFit = MAX_DATA_SPACE - COMPRESSED_PLAIN_STRING_OVERHEAD - 2;
                strings.add(makeUnicodeString(almostPerfectFit));
                String oneCharString = new String(new char[1]);
                strings.add(makeUnicodeString(oneCharString));
-               confirmSize(SSTRecord.SST_RECORD_OVERHEAD
+               confirmSize(SST_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
                                + almostPerfectFit
                                // second string
-                               + SSTRecord.STD_RECORD_OVERHEAD
+                               + STD_RECORD_OVERHEAD
                                + COMPRESSED_PLAIN_STRING_OVERHEAD
                                + oneCharString.length());
 
index a6bcf3e607389855a8045750c6cb20f70ba75351..77449ca640b5f0029c9050ba0a975f3cd5b63568 100644 (file)
@@ -139,7 +139,7 @@ public final class TestTextObjectRecord extends TestCase {
         obj.setStr( str );
 
 
-        TextObjectRecord cloned = (TextObjectRecord)obj.clone();
+        TextObjectRecord cloned = obj.copy();
         assertEquals(obj.getRecordSize(), cloned.getRecordSize());
         assertEquals(obj.getHorizontalTextAlignment(), cloned.getHorizontalTextAlignment());
         assertEquals(obj.getStr().getString(), cloned.getStr().getString());
index 1a823e3aaaa2602a030cb9289cc1489716744433..d8f4b76b02eb62671717376546d9ff817935e305 100644 (file)
@@ -26,8 +26,6 @@ import java.io.IOException;
 import org.apache.poi.hssf.record.ContinueRecord;
 import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.hssf.record.common.UnicodeString.ExtRst;
-import org.apache.poi.hssf.record.common.UnicodeString.FormatRun;
 import org.apache.poi.hssf.record.cont.ContinuableRecordOutput;
 import org.apache.poi.hssf.usermodel.HSSFOptimiser;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@@ -93,9 +91,9 @@ public final class TestUnicodeString {
         //Test a compressed small string that has rich text formatting
         s.setString("Test");
         s.setOptionFlags((byte)0x8);
-        UnicodeString.FormatRun r = new UnicodeString.FormatRun((short)0,(short)1);
+        FormatRun r = new FormatRun((short)0,(short)1);
         s.addFormatRun(r);
-        UnicodeString.FormatRun r2 = new UnicodeString.FormatRun((short)2,(short)2);
+        FormatRun r2 = new FormatRun((short)2,(short)2);
         s.addFormatRun(r2);
         confirmSize(17, s);
 
@@ -108,7 +106,7 @@ public final class TestUnicodeString {
         s.setString("Test");
         s.setOptionFlags((byte)0xC);
         confirmSize(17, s);
-        
+
         // Extended phonetics data
         // Minimum size is 14
         // Also adds 4 bytes to hold the length
@@ -121,7 +119,7 @@ public final class TestUnicodeString {
         s.setString(STR_16_BIT);
         s.setOptionFlags((byte)0xD);
         confirmSize(39, s);
-        
+
         s.setExtendedRst(null);
         confirmSize(21, s);
     }
@@ -144,8 +142,8 @@ public final class TestUnicodeString {
     public void perfectRichStringSize() {
       //Test a rich text string
       UnicodeString s = makeUnicodeString(MAX_DATA_SIZE-2-1-8-2);
-      s.addFormatRun(new UnicodeString.FormatRun((short)1,(short)0));
-      s.addFormatRun(new UnicodeString.FormatRun((short)2,(short)1));
+      s.addFormatRun(new FormatRun((short)1,(short)0));
+      s.addFormatRun(new FormatRun((short)2,(short)1));
       s.setOptionFlags((byte)0x8);
       confirmSize(MAX_DATA_SIZE, s);
 
@@ -153,8 +151,8 @@ public final class TestUnicodeString {
       //Note that we can only ever get to a maximum size of 8227 since an uncompressed
       //string is writing double bytes.
       s = makeUnicodeString((MAX_DATA_SIZE-2-1-8-2)/2, true);
-      s.addFormatRun(new UnicodeString.FormatRun((short)1,(short)0));
-      s.addFormatRun(new UnicodeString.FormatRun((short)2,(short)1));
+      s.addFormatRun(new FormatRun((short)1,(short)0));
+      s.addFormatRun(new FormatRun((short)2,(short)1));
       s.setOptionFlags((byte)0x9);
       confirmSize(MAX_DATA_SIZE-1, s);
     }
@@ -180,25 +178,25 @@ public final class TestUnicodeString {
       UnicodeString s = makeUnicodeString(strSize);
       confirmSize(MAX_DATA_SIZE*2, s);
     }
-    
+
     @Test
     public void formatRun() {
        FormatRun fr = new FormatRun((short)4, (short)0x15c);
        assertEquals(4, fr.getCharacterPos());
        assertEquals(0x15c, fr.getFontIndex());
-       
+
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        LittleEndianOutputStream out = new LittleEndianOutputStream(baos);
-       
+
        fr.serialize(out);
-       
+
        byte[] b = baos.toByteArray();
        assertEquals(4, b.length);
        assertEquals(4, b[0]);
        assertEquals(0, b[1]);
        assertEquals(0x5c, b[2]);
        assertEquals(0x01, b[3]);
-       
+
        LittleEndianInputStream inp = new LittleEndianInputStream(
              new ByteArrayInputStream(b)
        );
@@ -206,34 +204,34 @@ public final class TestUnicodeString {
        assertEquals(4, fr.getCharacterPos());
        assertEquals(0x15c, fr.getFontIndex());
     }
-    
+
     @Test
     public void extRstFromEmpty() {
        ExtRst ext = new ExtRst();
-       
+
        assertEquals(0, ext.getNumberOfRuns());
        assertEquals(0, ext.getFormattingFontIndex());
        assertEquals(0, ext.getFormattingOptions());
        assertEquals("", ext.getPhoneticText());
        assertEquals(0, ext.getPhRuns().length);
        assertEquals(10, ext.getDataSize()); // Excludes 4 byte header
-       
+
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        LittleEndianOutputStream out = new LittleEndianOutputStream(baos);
        ContinuableRecordOutput cout = new ContinuableRecordOutput(out, 0xffff);
-       
+
        ext.serialize(cout);
        cout.writeContinue();
-       
+
        byte[] b = baos.toByteArray();
        assertEquals(20, b.length);
-       
+
        // First 4 bytes from the outputstream
        assertEquals(-1, b[0]);
        assertEquals(-1, b[1]);
        assertEquals(14, b[2]);
        assertEquals(0, b[3]);
-       
+
        // Reserved
        assertEquals(1, b[4]);
        assertEquals(0, b[5]);
@@ -253,12 +251,12 @@ public final class TestUnicodeString {
        assertEquals(0, b[15]);
        assertEquals(0, b[16]);
        assertEquals(0, b[17]);
-       
+
        // Last 2 bytes from the outputstream
        assertEquals(ContinueRecord.sid, b[18]);
        assertEquals(0, b[19]);
-       
-       
+
+
        // Load in again and re-test
        byte[] data = new byte[14];
        System.arraycopy(b, 4, data, 0, data.length);
@@ -266,14 +264,14 @@ public final class TestUnicodeString {
              new ByteArrayInputStream(data)
        );
        ext = new ExtRst(inp, data.length);
-       
+
        assertEquals(0, ext.getNumberOfRuns());
        assertEquals(0, ext.getFormattingFontIndex());
        assertEquals(0, ext.getFormattingOptions());
        assertEquals("", ext.getPhoneticText());
        assertEquals(0, ext.getPhRuns().length);
     }
-    
+
     @Test
     public void extRstFromData() {
        byte[] data = new byte[] {
@@ -284,39 +282,39 @@ public final class TestUnicodeString {
                0, 0 // Cruft at the end, as found from real files
        };
        assertEquals(16, data.length);
-       
+
        LittleEndianInputStream inp = new LittleEndianInputStream(
              new ByteArrayInputStream(data)
        );
        ExtRst ext = new ExtRst(inp, data.length);
        assertEquals(0x0c, ext.getDataSize()); // Excludes 4 byte header
-       
+
        assertEquals(0, ext.getNumberOfRuns());
        assertEquals(0x37, ext.getFormattingOptions());
        assertEquals(0, ext.getFormattingFontIndex());
        assertEquals("", ext.getPhoneticText());
        assertEquals(0, ext.getPhRuns().length);
     }
-    
+
     @Test
     public void corruptExtRstDetection() {
        byte[] data = new byte[] {
-             0x79, 0x79, 0x11, 0x11, 
-             0x22, 0x22, 0x33, 0x33, 
+             0x79, 0x79, 0x11, 0x11,
+             0x22, 0x22, 0x33, 0x33,
        };
        assertEquals(8, data.length);
-       
+
        LittleEndianInputStream inp = new LittleEndianInputStream(
              new ByteArrayInputStream(data)
        );
        ExtRst ext = new ExtRst(inp, data.length);
-       
+
        // Will be empty
        assertEquals(ext, new ExtRst());
 
        // If written, will be the usual size
        assertEquals(10, ext.getDataSize()); // Excludes 4 byte header
-     
+
        // Is empty
        assertEquals(0, ext.getNumberOfRuns());
        assertEquals(0, ext.getFormattingOptions());
@@ -342,12 +340,12 @@ public final class TestUnicodeString {
         bos.writeShort(1);
         bos.writeShort(3);
         bos.writeShort(42);
-        
+
         LittleEndianInput in = new LittleEndianByteArrayInputStream(buf, 0, bos.getWriteIndex());
-        UnicodeString.ExtRst extRst1 = new UnicodeString.ExtRst(in, bos.getWriteIndex());
+        ExtRst extRst1 = new ExtRst(in, bos.getWriteIndex());
         in = new LittleEndianByteArrayInputStream(buf, 0, bos.getWriteIndex());
-        UnicodeString.ExtRst extRst2 = new UnicodeString.ExtRst(in, bos.getWriteIndex());
-        
+        ExtRst extRst2 = new ExtRst(in, bos.getWriteIndex());
+
         assertEquals(extRst1, extRst2);
         assertEquals(extRst1.hashCode(), extRst2.hashCode());
     }
index e3f4aeaef24f5b1e54b979afe16e3ae13d5efcc8..f3bb535b12c17bbf42d613e3fbb286cca39f6773 100644 (file)
@@ -77,7 +77,7 @@ import org.junit.Test;
  */
 public final class TestHSSFWorkbook extends BaseTestWorkbook {
     private static final HSSFITestDataProvider _testDataProvider = HSSFITestDataProvider.instance;
-    
+
     public TestHSSFWorkbook() {
         super(_testDataProvider);
     }
@@ -215,10 +215,10 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         confirmActiveSelected(sheet2, true);
         confirmActiveSelected(sheet3, false);
         confirmActiveSelected(sheet4, false);
-        
+
         wb.close();
     }
-    
+
     private static List<Integer> arrayToList(int[] array) {
         List<Integer> list = new ArrayList<>(array.length);
         for ( Integer element : array ) {
@@ -226,7 +226,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         }
         return list;
     }
-    
+
     private static void assertCollectionsEquals(Collection<Integer> expected, Collection<Integer> actual) {
         assertEquals("size", expected.size(), actual.size());
         for (int e : expected) {
@@ -247,7 +247,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         HSSFSheet sheet4 = wb.createSheet("Sheet4");
         HSSFSheet sheet5 = wb.createSheet("Sheet5");
 
-        
+
         List<Integer> selected = arrayToList(new int[] { 0, 2, 3 });
         wb.setSelectedTabs(selected);
 
@@ -292,7 +292,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                 throw new RuntimeException(e);
             }
         }*/
-        
+
         wb.close();
     }
 
@@ -358,7 +358,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         // The last remaining sheet should always be active+selected
         wb.removeSheetAt(1);
         confirmActiveSelected(sheet0, true,  true);
-        
+
         wb.close();
     }
 
@@ -394,7 +394,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             // Expected badly behaved sheet record to cause exception
             assertTrue(e.getMessage().startsWith("Actual serialized sheet size"));
         }
-        
+
         wb.close();
     }
 
@@ -482,7 +482,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         assertEquals("OnSheet3", n.getNameName());
         assertEquals("Sheet3", n.getSheetName());
         assertEquals("Sheet3!$A$1:$A$2", n.getRefersToFormula());
-        
+
         b.close();
     }
 
@@ -505,6 +505,10 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                public int getRecordSize() {
             return 8;
         }
+        @Override
+        public BadlyBehavedRecord copy() {
+            return null;
+        }
     }
 
     /**
@@ -571,12 +575,12 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         ClassID clsid2 = fs2.getRoot().getStorageClsid();
 
         assertEquals(clsid1, clsid2);
-        
+
         fs2.close();
         wb.close();
         fs1.close();
     }
-    
+
     /**
      * If we try to open an old (pre-97) workbook, we get a helpful
      *  Exception give to explain what we've done wrong
@@ -591,7 +595,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             assertContains(e.getMessage(), "BIFF4");
         }
         excel4.close();
-        
+
         InputStream excel5 = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("testEXCEL_5.xls");
         try {
             new HSSFWorkbook(excel5).close();
@@ -600,7 +604,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             assertContains(e.getMessage(), "BIFF5");
         }
         excel5.close();
-        
+
         InputStream excel95 = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("testEXCEL_95.xls");
         try {
             new HSSFWorkbook(excel95).close();
@@ -722,7 +726,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                     "You can define up to 4000 styles in a .xls workbook", e.getMessage());
         }
         assertEquals(MAX_STYLES, wb.getNumCellStyles());
-        
+
         wb.close();
     }
 
@@ -809,7 +813,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             EscherBSERecord bse = iwb.getBSERecord(pictureIndex);
             assertEquals(3, bse.getRef());
         }
-        
+
         wb.close();
     }
 
@@ -829,7 +833,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
     @Test
     public void selectedSheetShort() throws IOException {
         HSSFWorkbook wb=new HSSFWorkbook();
-        
+
         HSSFSheet sheet1 = wb.createSheet("Sheet1");
         HSSFSheet sheet2 = wb.createSheet("Sheet2");
         HSSFSheet sheet3 = wb.createSheet("Sheet3");
@@ -895,7 +899,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         } catch (IllegalArgumentException e) {
             assertTrue(e.getMessage(), e.getMessage().contains("outside the allowable range"));
         }
-        
+
         wb.close();
     }
 
@@ -905,7 +909,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         wb.insertChartRecord();
         //wb.dumpDrawingGroupRecords(true);
         //wb.dumpDrawingGroupRecords(false);
-        
+
         wb.close();
     }
 
@@ -917,7 +921,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
 
         wb.writeProtectWorkbook("mypassword", "myuser");
         assertTrue(wb.isWriteProtected());
-        
+
 //        OutputStream os = new FileOutputStream("/tmp/protected.xls");
 //        try {
 //            wb.write(os);
@@ -1008,7 +1012,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                read.close();
                wb.close();
        }
-       
+
     @Test
        public void bug54500() throws Exception {
                String nameName = "AName";
@@ -1016,7 +1020,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("54500.xls");
 
                assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3");
-               
+
                wb.createSheet(sheetName);
 
                assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3", "ASheet");
@@ -1030,7 +1034,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         final HSSFName name = wb.getName(nameName);
         assertNotNull(name);
         assertEquals("ASheet!A1", name.getRefersToFormula());
-               
+
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                wb.write(stream);
 
@@ -1068,7 +1072,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
        public void test49423() throws Exception
     {
                HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("49423.xls");
-               
+
                boolean found = false;
         int numSheets = workbook.getNumberOfSheets();
         for (int i = 0; i < numSheets; i++) {
@@ -1076,7 +1080,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             List<HSSFShape> shapes = sheet.getDrawingPatriarch().getChildren();
             for(HSSFShape shape : shapes){
                 HSSFAnchor anchor = shape.getAnchor();
-    
+
                 if(anchor instanceof HSSFClientAnchor){
                     // absolute coordinates
                     HSSFClientAnchor clientAnchor = (HSSFClientAnchor)anchor;
@@ -1084,7 +1088,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                     //System.out.println(clientAnchor.getRow1() + "," + clientAnchor.getRow2());
                     found = true;
                 } else if (anchor instanceof HSSFChildAnchor){
-                    // shape is grouped and the anchor is expressed in the coordinate system of the group 
+                    // shape is grouped and the anchor is expressed in the coordinate system of the group
                     HSSFChildAnchor childAnchor = (HSSFChildAnchor)anchor;
                     assertNotNull(childAnchor);
                     //System.out.println(childAnchor.getDy1() + "," + childAnchor.getDy2());
@@ -1092,7 +1096,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                 }
             }
         }
-        
+
         assertTrue("Should find some images via Client or Child anchors, but did not find any at all", found);
         workbook.close();
     }
@@ -1108,10 +1112,10 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
                 final Sheet sheet = workbook.createSheet("foo");
                 final Row row = sheet.createRow(1);
                 row.createCell(1).setCellValue("bar");
-                
+
                 writeAndCloseWorkbook(workbook, file);
             }
-    
+
             // edit the workbook
             {
                 try (POIFSFileSystem fs = new POIFSFileSystem(file, false)) {
@@ -1143,17 +1147,17 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         fileOut.close();
 
     }
-    
+
     @Test
     public void closeDoesNotModifyWorkbook() throws IOException {
         final String filename = "SampleSS.xls";
         final File file = POIDataSamples.getSpreadSheetInstance().getFile(filename);
         Workbook wb;
-        
+
         // File via POIFileStream (java.nio)
         wb = new HSSFWorkbook(new POIFSFileSystem(file));
         assertCloseDoesNotModifyFile(filename, wb);
-        
+
         // InputStream
         wb = new HSSFWorkbook(new FileInputStream(file));
         assertCloseDoesNotModifyFile(filename, wb);
@@ -1171,11 +1175,11 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             throw new Exception("Moving a sheet to the end should not throw an exception, but threw ", e);
         }
     }
-    
+
     @Test
     public void invalidInPlaceWrite() throws Exception {
         HSSFWorkbook wb;
-        
+
         // Can't work for new files
         wb = new HSSFWorkbook();
         try {
@@ -1185,7 +1189,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             // expected here
         }
         wb.close();
-        
+
         // Can't work for InputStream opened files
         wb = new HSSFWorkbook(
             POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SampleSS.xls"));
@@ -1196,7 +1200,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
             // expected here
         }
         wb.close();
-        
+
         // Can't work for Read-Only files
         POIFSFileSystem fs = new POIFSFileSystem(
                 POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls"), true);
@@ -1209,7 +1213,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         }
         wb.close();
     }
-    
+
     @Test
     public void inPlaceWrite() throws Exception {
         // Setup as a copy of a known-good file
@@ -1218,27 +1222,27 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
              FileOutputStream outputStream = new FileOutputStream(file)) {
             IOUtils.copy(inputStream, outputStream);
         }
-        
+
         // Open from the temp file in read-write mode
         HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(file, false));
         assertEquals(3, wb.getNumberOfSheets());
-        
+
         // Change
         wb.removeSheetAt(2);
         wb.removeSheetAt(1);
         wb.getSheetAt(0).getRow(0).getCell(0).setCellValue("Changed!");
-        
+
         // Save in-place, close, re-open and check
         wb.write();
         wb.close();
-        
+
         wb = new HSSFWorkbook(new POIFSFileSystem(file));
         assertEquals(1, wb.getNumberOfSheets());
         assertEquals("Changed!", wb.getSheetAt(0).getRow(0).getCell(0).toString());
 
         wb.close();
     }
-    
+
     @Test
     public void testWriteToNewFile() throws Exception {
         // Open from a Stream
@@ -1249,13 +1253,13 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
         final File file = TempFile.createTempFile("TestHSSFWorkbook", ".xls");
         wb.write(file);
         wb.close();
-        
+
         // Read and check
         wb = new HSSFWorkbook(new POIFSFileSystem(file));
         assertEquals(3, wb.getNumberOfSheets());
         wb.close();
     }
-    
+
     @Ignore
     @Test
     @Override
index bf17bca54fb2655e8567d10f932bc9e4310c43a2..0dbd1e6ae6f223ade373f96ec17550ac52ce6e4d 100644 (file)
@@ -41,7 +41,7 @@ public class TestAbstractFunctionPtg  {
     public void testInvalidRuntimeClass() {
         new FunctionPtg(1, 300, null, 255);
     }
-    
+
     private static class FunctionPtg extends AbstractFunctionPtg {
 
         protected FunctionPtg(int functionIndex, int pReturnClass,
@@ -54,7 +54,13 @@ public class TestAbstractFunctionPtg  {
         }
 
         public void write(LittleEndianOutput out) {
-            
+
+        }
+
+        @Override
+        public FunctionPtg copy() {
+            // immutable
+            return this;
         }
     }
 }