diff --git a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java index 4878299981..c01cf77a34 100644 --- a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java @@ -64,7 +64,7 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { out.writeShort(field_5_reserved); field_7_parsed_expr.serialize(out); } - + protected int getExtraDataSize() { return 2 + field_7_parsed_expr.getEncodedSize(); } @@ -98,8 +98,8 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { /** * Creates a non shared formula from the shared formula counterpart
- * - * Perhaps this functionality could be implemented in terms of the raw + * + * Perhaps this functionality could be implemented in terms of the raw * byte array inside {@link Formula}. */ public static Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) { @@ -113,14 +113,15 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { originalOperandClass = ptg.getPtgClass(); } if (ptg instanceof RefPtgBase) { - RefPtgBase refNPtg = (RefPtgBase)ptg; - ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), + RefPtgBase refNPtg = (RefPtgBase)ptg; + ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()), refNPtg.isRowRelative(), refNPtg.isColRelative()); + ptg.setClass(originalOperandClass); } else if (ptg instanceof AreaPtgBase) { - AreaPtgBase areaNPtg = (AreaPtgBase)ptg; - ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()), + AreaPtgBase areaNPtg = (AreaPtgBase)ptg; + ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()), fixupRelativeRow(formulaRow,areaNPtg.getLastRow(),areaNPtg.isLastRowRelative()), fixupRelativeColumn(formulaColumn,areaNPtg.getFirstColumn(),areaNPtg.isFirstColRelative()), fixupRelativeColumn(formulaColumn,areaNPtg.getLastColumn(),areaNPtg.isLastColRelative()), @@ -128,15 +129,13 @@ public final class SharedFormulaRecord extends SharedValueRecordBase { areaNPtg.isLastRowRelative(), areaNPtg.isFirstColRelative(), areaNPtg.isLastColRelative()); - } else { - if (false) {// do we need a ptg clone here? - ptg = ptg.copy(); - } - } - if (!ptg.isBaseToken()) { ptg.setClass(originalOperandClass); + } else if (ptg instanceof OperandPtg) { + // Any subclass of OperandPtg is mutable, so it's safest to not share these instances. + ptg = ((OperandPtg) ptg).copy(); + } else { + // all other Ptgs are immutable and can be shared } - newPtgStack[k] = ptg; } return newPtgStack; diff --git a/src/java/org/apache/poi/hssf/record/TextObjectRecord.java b/src/java/org/apache/poi/hssf/record/TextObjectRecord.java index 06fb3e4319..68398bb70c 100644 --- a/src/java/org/apache/poi/hssf/record/TextObjectRecord.java +++ b/src/java/org/apache/poi/hssf/record/TextObjectRecord.java @@ -19,6 +19,7 @@ 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.hssf.record.formula.OperandPtg; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.util.BitField; @@ -74,13 +75,14 @@ public final class TextObjectRecord extends ContinuableRecord { */ private int _unknownPreFormulaInt; /** expect tRef, tRef3D, tArea, tArea3D or tName */ - private Ptg _linkRefPtg; + private OperandPtg _linkRefPtg; /** * Not clear if needed . Excel seems to be OK if this byte is not present. * Value is often the same as the earlier firstColumn byte. */ private Byte _unknownPostFormulaByte; public TextObjectRecord() { + // } public TextObjectRecord(RecordInputStream in) { @@ -106,7 +108,7 @@ public final class TextObjectRecord extends ContinuableRecord { throw new RecordFormatException("Read " + ptgs.length + " tokens but expected exactly 1"); } - _linkRefPtg = ptgs[0]; + _linkRefPtg = (OperandPtg) ptgs[0]; if (in.remaining() > 0) { _unknownPostFormulaByte = Byte.valueOf(in.readByte()); } else { diff --git a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java index aec3e03503..264b448ca6 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java @@ -32,10 +32,10 @@ import org.apache.poi.util.LittleEndianOutput; * @author avik * @author Jason Height (jheight at chariot dot net dot au) */ -public final class Area3DPtg extends AreaPtgBase implements WorkbookDependentFormula, ExternSheetReferenceToken { +public final class Area3DPtg extends AreaPtgBase implements WorkbookDependentFormula, ExternSheetReferenceToken { public final static byte sid = 0x3b; private final static int SIZE = 11; // 10 + 1 for Ptg - + private int field_1_index_extern_sheet; diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java index 5cd5a9b748..d50fca02f9 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java +++ b/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java @@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndianOutput; * @author andy * @author Jason Height (jheight at chariot dot net dot au) */ -public abstract class AreaPtgBase extends OperandPtg implements AreaI { +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 @@ -96,17 +96,6 @@ public abstract class AreaPtgBase extends OperandPtg implements AreaI { } } - private static void $checkColumnBounds(int colIx) { - if((colIx & 0x0FF) != colIx) { - throw new IllegalArgumentException("colIx (" + colIx + ") is out of range"); - } - } - private static void $checkRowBounds(int rowIx) { - if((rowIx & 0x0FFFF) != rowIx) { - throw new IllegalArgumentException("rowIx (" + rowIx + ") is out of range"); - } - } - protected final void readCoordinates(LittleEndianInput in) { field_1_first_row = in.readUShort(); field_2_last_row = in.readUShort(); diff --git a/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java b/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java index 5cec763e13..bbfb95a729 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java @@ -260,14 +260,4 @@ public final class AttrPtg extends ControlPtg { } return "UNKNOWN ATTRIBUTE"; } - - public Object clone() { - int[] jt; - if (_jumpTable == null) { - jt = null; - } else { - jt = _jumpTable.clone(); - } - return new AttrPtg(_options, _data, jt, _chooseFuncOffset); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/OperandPtg.java b/src/java/org/apache/poi/hssf/record/formula/OperandPtg.java index 0c1d1faeb8..bd1490289c 100644 --- a/src/java/org/apache/poi/hssf/record/formula/OperandPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/OperandPtg.java @@ -21,12 +21,21 @@ package org.apache.poi.hssf.record.formula; /** * @author Josh Micich */ -public abstract class OperandPtg extends Ptg { +public abstract class OperandPtg> extends Ptg implements Cloneable { /** - * All Operand Ptgs are classifed ('relative', 'value', 'array') + * All Operand {@link Ptg}s are classified ('relative', 'value', 'array') */ public final boolean isBaseToken() { return false; } + public final Y copy() { + try { + @SuppressWarnings("unchecked") + Y result = (Y) clone(); + return result; + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java index f2857a7dfa..2426249c15 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -40,7 +40,7 @@ import org.apache.poi.util.LittleEndianOutput; * @author avik * @author Jason Height (jheight at chariot dot net dot au) */ -public abstract class Ptg implements Cloneable { +public abstract class Ptg { public static final Ptg[] EMPTY_PTG_ARRAY = { }; @@ -158,28 +158,7 @@ public abstract class Ptg implements Cloneable { } throw new RuntimeException("Unexpected base token id (" + id + ")"); } - /** - * @return a distinct copy of this Ptg if the class is mutable, or the same instance - * if the class is immutable. - */ - public final Ptg copy() { - // TODO - all base tokens are logically immutable, but AttrPtg needs some clean-up - if (this instanceof ValueOperatorPtg) { - return this; - } - if (this instanceof ScalarConstantPtg) { - return this; - } - return (Ptg) clone(); - } - protected Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } private static Ptg[] toPtgArray(List l) { if (l.isEmpty()) { return EMPTY_PTG_ARRAY; diff --git a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java index c695932a1c..13a7f05899 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java @@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndianOutput; * @author Libin Roman (Vista Portal LDT. Developer) * @author Jason Height (jheight at chariot dot net dot au) */ -public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormula, ExternSheetReferenceToken { +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 @@ -42,7 +42,7 @@ public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormu field_1_index_extern_sheet = in.readShort(); readCoordinates(in); } - + public Ref3DPtg(String cellref, int externIdx ) { this(new CellReference(cellref), externIdx); } @@ -82,7 +82,7 @@ public final class Ref3DPtg extends RefPtgBase implements WorkbookDependentFormu } /** - * @return text representation of this cell reference that can be used in text + * @return text representation of this cell reference that can be used in text * formulas. The sheet name will get properly delimited if required. */ public String toFormulaString(FormulaRenderingWorkbook book) { diff --git a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java index 70ed4da87a..28e7ebd9fb 100644 --- a/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java @@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndianOutput; * @author Andrew C. Oliver (acoliver@apache.org) * @author Jason Height (jheight at chariot dot net dot au) */ -public abstract class RefPtgBase extends OperandPtg { +public abstract class RefPtgBase> extends OperandPtg { /** The row index - zero based unsigned 16 bit value */ private int field_1_row; diff --git a/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java b/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java index d441a0098d..ca94766a5e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java @@ -19,8 +19,7 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.util.LittleEndianOutput; /** - * - * @author andy + * @author andy * @author Jason Height (jheight at chariot dot net dot au) */ public class UnknownPtg extends Ptg { @@ -38,18 +37,14 @@ public class UnknownPtg extends Ptg { out.writeByte(_sid); } - public int getSize() - { + public int getSize() { return size; } - public String toFormulaString() - { + public String toFormulaString() { return "UNKNOWN"; } - public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} - - public Object clone() { - return this; + public byte getDefaultOperandClass() { + return Ptg.CLASS_VALUE; } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 3d81c478f4..612eb67b18 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -676,16 +676,16 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm Ptg[] ptgs = origNameRecord.getNameDefinition(); for (int i=0; i< ptgs.length; i++) { Ptg ptg = ptgs[i]; - ptg = ptg.copy(); if (ptg instanceof Area3DPtg) { - Area3DPtg a3p = (Area3DPtg) ptg; + Area3DPtg a3p = ((Area3DPtg) ptg).copy(); a3p.setExternSheetIndex(newExtSheetIx); + ptgs[i] = a3p; } else if (ptg instanceof Ref3DPtg) { - Ref3DPtg r3p = (Ref3DPtg) ptg; + Ref3DPtg r3p = ((Ref3DPtg) ptg).copy(); r3p.setExternSheetIndex(newExtSheetIx); + ptgs[i] = r3p; } - ptgs[i] = ptg; } NameRecord newNameRecord = workbook.createBuiltInName(NameRecord.BUILTIN_FILTER_DB, newSheetIndex+1); newNameRecord.setNameDefinition(ptgs); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java index 399e80c240..52121728c3 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java @@ -28,11 +28,8 @@ import org.apache.poi.hssf.record.TestcaseRecordInputStream; public final class TestFuncPtg extends TestCase { public void testRead() { - // This ptg represents a LEN function extracted from excel - byte[] fakeData = { - 0x20, //function index - 0, - }; + // This function index represents the LEN() function + byte[] fakeData = { 0x20, 0x00,}; FuncPtg ptg = FuncPtg.create(TestcaseRecordInputStream.createLittleEndian(fakeData) ); assertEquals( "Len formula index is not 32(20H)", 0x20, ptg.getFunctionIndex() ); @@ -41,14 +38,9 @@ public final class TestFuncPtg extends TestCase { assertEquals( "Ptg Size", 3, ptg.getSize() ); } - public void testClone() { + public void testNumberOfOperands() { FuncPtg funcPtg = FuncPtg.create(27); // ROUND() - takes 2 args - - FuncPtg clone = (FuncPtg) funcPtg.clone(); - if (clone.getNumberOfOperands() == 0) { - fail("clone() did copy field numberOfOperands"); - } - assertEquals(2, clone.getNumberOfOperands()); - assertEquals("ROUND", clone.getName()); + assertEquals(2, funcPtg.getNumberOfOperands()); + assertEquals("ROUND", funcPtg.getName()); } }