diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index 267811d78..43b373d04 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -46,6 +46,11 @@ Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx + 44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size + Support custom image renderers in HSLF + Correctly increment the reference count of a blip when a picture is inserted + 45110 - Fixed TextShape.resizeToFitText() to properly resize TextShape + 45091 - Fixed serialization of RefN~ tokens. Simplified Ptg class hierarchy 45133 - Fixed OBJ Record (5Dh) to pad the sub-record data to a 4-byte boundary 45145 - Fixed Sheet to always enforce RowRecordsAggregate before ValueRecordsAggregate 45123 - Fixed SharedFormulaRecord.convertSharedFormulas() to propagate token operand classes diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 115db4e10..3ad07a216 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -43,6 +43,11 @@ Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx + 44692 - Fixed HSSFPicture.resize() to properly resize pictures if the underlying columns/rows have modified size + Support custom image renderers in HSLF + Correctly increment the reference count of a blip when a picture is inserted + 45110 - Fixed TextShape.resizeToFitText() to properly resize TextShape + 45091 - Fixed serialization of RefN~ tokens. Simplified Ptg class hierarchy 45133 - Fixed OBJ Record (5Dh) to pad the sub-record data to a 4-byte boundary 45145 - Fixed Sheet to always enforce RowRecordsAggregate before ValueRecordsAggregate 45123 - Fixed SharedFormulaRecord.convertSharedFormulas() to propagate token operand classes diff --git a/src/java/org/apache/poi/ddf/EscherDggRecord.java b/src/java/org/apache/poi/ddf/EscherDggRecord.java index 0ff00016d..cdc9281a8 100644 --- a/src/java/org/apache/poi/ddf/EscherDggRecord.java +++ b/src/java/org/apache/poi/ddf/EscherDggRecord.java @@ -238,6 +238,10 @@ public class EscherDggRecord return maxDgId; } + public void setMaxDrawingGroupId(int id){ + maxDgId = id; + } + public FileIdCluster[] getFileIdClusters() { return field_5_fileIdClusters; diff --git a/src/java/org/apache/poi/hssf/model/FormulaParser.java b/src/java/org/apache/poi/hssf/model/FormulaParser.java index d45e8741b..501b030ec 100644 --- a/src/java/org/apache/poi/hssf/model/FormulaParser.java +++ b/src/java/org/apache/poi/hssf/model/FormulaParser.java @@ -97,7 +97,7 @@ public final class FormulaParser { * parse results. * This class is recommended only for single threaded use. * - * If you only have a usermodel.HSSFWorkbook, and not a + * If you only have a usermodel.Workbook, and not a * model.Workbook, then use the convenience method on * usermodel.HSSFFormulaEvaluator */ @@ -274,7 +274,7 @@ public final class FormulaParser { boolean cellRef = CELL_REFERENCE_PATTERN.matcher(name).matches(); if (cellRef) { - return new ReferencePtg(name); + return new RefPtg(name); } for(int i = 0; i < book.getNumberOfNames(); i++) { @@ -324,9 +324,9 @@ public final class FormulaParser { FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByName(name.toUpperCase()); int numArgs = args.length; if(fm == null) { - if (namePtg == null) { - throw new IllegalStateException("NamePtg must be supplied for external functions"); - } + if (namePtg == null) { + throw new IllegalStateException("NamePtg must be supplied for external functions"); + } // must be external function ParseNode[] allArgs = new ParseNode[numArgs+1]; allArgs[0] = new ParseNode(namePtg); @@ -335,8 +335,8 @@ public final class FormulaParser { } if (namePtg != null) { - throw new IllegalStateException("NamePtg no applicable to internal functions"); - } + throw new IllegalStateException("NamePtg no applicable to internal functions"); + } boolean isVarArgs = !fm.hasFixedArgsLength(); int funcIx = fm.getIndex(); validateNumArgs(args.length, fm); @@ -392,7 +392,7 @@ public final class FormulaParser { SkipWhite(); if (isArgumentDelimiter(look)) { if (missedPrevArg) { - temp.add(new ParseNode(new MissingArgPtg())); + temp.add(new ParseNode(MissingArgPtg.instance)); numArgs++; } if (look == ')') { @@ -417,7 +417,7 @@ public final class FormulaParser { /** Parse and Translate a Math Factor */ private ParseNode powerFactor() { - ParseNode result = percentFactor(); + ParseNode result = percentFactor(); while(true) { SkipWhite(); if(look != '^') { @@ -425,19 +425,19 @@ public final class FormulaParser { } Match('^'); ParseNode other = percentFactor(); - result = new ParseNode(new PowerPtg(), result, other); + result = new ParseNode(PowerPtg.instance, result, other); } } private ParseNode percentFactor() { - ParseNode result = parseSimpleFactor(); + ParseNode result = parseSimpleFactor(); while(true) { SkipWhite(); if(look != '%') { return result; } Match('%'); - result = new ParseNode(new PercentPtg(), result); + result = new ParseNode(PercentPtg.instance, result); } } @@ -452,15 +452,15 @@ public final class FormulaParser { return new ParseNode(parseErrorLiteral()); case '-': Match('-'); - return new ParseNode(new UnaryMinusPtg(), powerFactor()); + return new ParseNode(UnaryMinusPtg.instance, powerFactor()); case '+': Match('+'); - return new ParseNode(new UnaryPlusPtg(), powerFactor()); + return new ParseNode(UnaryPlusPtg.instance, powerFactor()); case '(': Match('('); ParseNode inside = comparisonExpression(); Match(')'); - return new ParseNode(new ParenthesisPtg(), inside); + return new ParseNode(ParenthesisPtg.instance, inside); case '"': return new ParseNode(parseStringLiteral()); } @@ -625,18 +625,18 @@ public final class FormulaParser { /** Parse and Translate a Math Term */ private ParseNode Term() { - ParseNode result = powerFactor(); + ParseNode result = powerFactor(); while(true) { SkipWhite(); Ptg operator; switch(look) { case '*': Match('*'); - operator = new MultiplyPtg(); + operator = MultiplyPtg.instance; break; case '/': Match('/'); - operator = new DividePtg(); + operator = DividePtg.instance; break; default: return result; // finished with Term @@ -647,7 +647,7 @@ public final class FormulaParser { } private ParseNode comparisonExpression() { - ParseNode result = concatExpression(); + ParseNode result = concatExpression(); while (true) { SkipWhite(); switch(look) { @@ -666,26 +666,26 @@ public final class FormulaParser { private Ptg getComparisonToken() { if(look == '=') { Match(look); - return new EqualPtg(); + return EqualPtg.instance; } boolean isGreater = look == '>'; Match(look); if(isGreater) { if(look == '=') { Match('='); - return new GreaterEqualPtg(); + return GreaterEqualPtg.instance; } - return new GreaterThanPtg(); + return GreaterThanPtg.instance; } switch(look) { case '=': Match('='); - return new LessEqualPtg(); + return LessEqualPtg.instance; case '>': Match('>'); - return new NotEqualPtg(); + return NotEqualPtg.instance; } - return new LessThanPtg(); + return LessThanPtg.instance; } @@ -698,7 +698,7 @@ public final class FormulaParser { } Match('&'); ParseNode other = additiveExpression(); - result = new ParseNode(new ConcatPtg(), result, other); + result = new ParseNode(ConcatPtg.instance, result, other); } return result; } @@ -706,18 +706,18 @@ public final class FormulaParser { /** Parse and Translate an Expression */ private ParseNode additiveExpression() { - ParseNode result = Term(); + ParseNode result = Term(); while (true) { SkipWhite(); Ptg operator; switch(look) { case '+': Match('+'); - operator = new AddPtg(); + operator = AddPtg.instance; break; case '-': Match('-'); - operator = new SubtractPtg(); + operator = SubtractPtg.instance; break; default: return result; // finished with additive expression @@ -743,7 +743,7 @@ end; /** * API call to execute the parsing of the formula - * @deprecated use Ptg[] FormulaParser.parse(String, HSSFWorkbook) directly + * @deprecated use Ptg[] FormulaParser.parse(String, Workbook) directly */ public void parse() { pointer=0; @@ -771,9 +771,9 @@ end; } public Ptg[] getRPNPtg(int formulaType) { - OperandClassTransformer oct = new OperandClassTransformer(formulaType); + OperandClassTransformer oct = new OperandClassTransformer(formulaType); // RVA is for 'operand class': 'reference', 'value', 'array' - oct.transformFormula(_rootNode); + oct.transformFormula(_rootNode); return ParseNode.toTokenArray(_rootNode); } diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index c20f5e6d3..1583aa039 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -557,7 +557,7 @@ public final class FormulaRecord if (field_8_parsed_expr != null) size = field_8_parsed_expr.size(); for (int i=0; i< size; i++) { - Ptg ptg = (Ptg)((Ptg)field_8_parsed_expr.get(i)).clone(); + Ptg ptg = ((Ptg)field_8_parsed_expr.get(i)).copy(); rec.field_8_parsed_expr.add(i, ptg); } rec.value_data = value_data; diff --git a/src/java/org/apache/poi/hssf/record/NameRecord.java b/src/java/org/apache/poi/hssf/record/NameRecord.java index 23af4b17c..786c0b3d6 100644 --- a/src/java/org/apache/poi/hssf/record/NameRecord.java +++ b/src/java/org/apache/poi/hssf/record/NameRecord.java @@ -737,7 +737,7 @@ public class NameRecord extends Record { } // And then a union if we had more than one area if(refs.length > 1) { - ptg = new UnionPtg(); + ptg = UnionPtg.instance; field_13_name_definition.push(ptg); this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) ); } diff --git a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java index e4c0f28ea..a8aeed0da 100755 --- a/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java @@ -207,22 +207,10 @@ public final class SharedFormulaRecord extends Record { } if (ptg instanceof RefNPtg) { RefNPtg refNPtg = (RefNPtg)ptg; - ptg = new ReferencePtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), + ptg = new RefPtg(fixupRelativeRow(formulaRow,refNPtg.getRow(),refNPtg.isRowRelative()), fixupRelativeColumn(formulaColumn,refNPtg.getColumn(),refNPtg.isColRelative()), refNPtg.isRowRelative(), refNPtg.isColRelative()); - } else if (ptg instanceof RefNVPtg) { - RefNVPtg refNVPtg = (RefNVPtg)ptg; - ptg = new RefVPtg(fixupRelativeRow(formulaRow,refNVPtg.getRow(),refNVPtg.isRowRelative()), - fixupRelativeColumn(formulaColumn,refNVPtg.getColumn(),refNVPtg.isColRelative()), - refNVPtg.isRowRelative(), - refNVPtg.isColRelative()); - } else if (ptg instanceof RefNAPtg) { - RefNAPtg refNAPtg = (RefNAPtg)ptg; - ptg = new RefAPtg( fixupRelativeRow(formulaRow,refNAPtg.getRow(),refNAPtg.isRowRelative()), - fixupRelativeColumn(formulaColumn,refNAPtg.getColumn(),refNAPtg.isColRelative()), - refNAPtg.isRowRelative(), - refNAPtg.isColRelative()); } else if (ptg instanceof AreaNPtg) { AreaNPtg areaNPtg = (AreaNPtg)ptg; ptg = new AreaPtg(fixupRelativeRow(formulaRow,areaNPtg.getFirstRow(),areaNPtg.isFirstRowRelative()), @@ -233,26 +221,6 @@ public final class SharedFormulaRecord extends Record { areaNPtg.isLastRowRelative(), areaNPtg.isFirstColRelative(), areaNPtg.isLastColRelative()); - } else if (ptg instanceof AreaNVPtg) { - AreaNVPtg areaNVPtg = (AreaNVPtg)ptg; - ptg = new AreaVPtg(fixupRelativeRow(formulaRow,areaNVPtg.getFirstRow(),areaNVPtg.isFirstRowRelative()), - fixupRelativeRow(formulaRow,areaNVPtg.getLastRow(),areaNVPtg.isLastRowRelative()), - fixupRelativeColumn(formulaColumn,areaNVPtg.getFirstColumn(),areaNVPtg.isFirstColRelative()), - fixupRelativeColumn(formulaColumn,areaNVPtg.getLastColumn(),areaNVPtg.isLastColRelative()), - areaNVPtg.isFirstRowRelative(), - areaNVPtg.isLastRowRelative(), - areaNVPtg.isFirstColRelative(), - areaNVPtg.isLastColRelative()); - } else if (ptg instanceof AreaNAPtg) { - AreaNAPtg areaNAPtg = (AreaNAPtg)ptg; - ptg = new AreaAPtg(fixupRelativeRow(formulaRow,areaNAPtg.getFirstRow(),areaNAPtg.isFirstRowRelative()), - fixupRelativeRow(formulaRow,areaNAPtg.getLastRow(),areaNAPtg.isLastRowRelative()), - fixupRelativeColumn(formulaColumn,areaNAPtg.getFirstColumn(),areaNAPtg.isFirstColRelative()), - fixupRelativeColumn(formulaColumn,areaNAPtg.getLastColumn(),areaNAPtg.isLastColRelative()), - areaNAPtg.isFirstRowRelative(), - areaNAPtg.isLastRowRelative(), - areaNAPtg.isFirstColRelative(), - areaNAPtg.isLastColRelative()); } if (!ptg.isBaseToken()) { ptg.setClass(originalOperandClass); diff --git a/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java b/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java index bda995066..fabc85ce5 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java @@ -56,12 +56,6 @@ public abstract class AbstractFunctionPtg extends OperationPtg { return sb.toString(); } - public int getType() { - return -1; - } - - - public short getFunctionIndex() { return field_2_fnc_index; } diff --git a/src/java/org/apache/poi/hssf/record/formula/AddPtg.java b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java index 20f609c56..db2d9d104 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AddPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AddPtg.java @@ -17,9 +17,6 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * Addition operator PTG the "+" binomial operator. If you need more * explanation than that then well...We really can't help you here. @@ -27,49 +24,23 @@ import org.apache.poi.hssf.record.RecordInputStream; * @author Jason Height (jheight at chariot dot net dot au) */ public final class AddPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x03; private final static String ADD = "+"; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new AddPtg(); - public AddPtg() - { - } - - public AddPtg(RecordInputStream in) - { - - // doesn't need anything + private AddPtg() { + // enforce singleton } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; + protected byte getSid() { + return sid; } - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - - /** Implementation of method from Ptg */ - public String toFormulaString(Workbook book) - { - return "+"; - } /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { @@ -80,9 +51,4 @@ public final class AddPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new AddPtg(); - } - } 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 e0411cd35..dab9cf3ce 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java @@ -18,9 +18,9 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ss.util.CellReference; import org.apache.poi.hssf.util.AreaReference; -import org.apache.poi.hssf.util.CellReference; +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; @@ -95,7 +95,7 @@ public class Area3DPtg extends OperandPtg implements AreaI { public void writeBytes( byte[] array, int offset ) { - array[0 + offset] = (byte) ( sid + ptgClass ); + array[0 + offset] = (byte) ( sid + getPtgClass() ); LittleEndian.putShort( array, 1 + offset, getExternSheetIndex() ); LittleEndian.putShort( array, 3 + offset, (short)getFirstRow() ); LittleEndian.putShort( array, 5 + offset, (short)getLastRow() ); @@ -280,24 +280,10 @@ public class Area3DPtg extends OperandPtg implements AreaI { return retval.toString(); } - public byte getDefaultOperandClass() - { + public byte getDefaultOperandClass() { return Ptg.CLASS_REF; } - - public Object clone() - { - Area3DPtg ptg = new Area3DPtg(); - ptg.field_1_index_extern_sheet = field_1_index_extern_sheet; - ptg.field_2_first_row = field_2_first_row; - ptg.field_3_last_row = field_3_last_row; - ptg.field_4_first_column = field_4_first_column; - ptg.field_5_last_column = field_5_last_column; - ptg.setClass(ptgClass); - return ptg; - } - - + // TODO - one junit relies on this. remove public boolean equals( Object o ) { if ( this == o ) return true; @@ -313,18 +299,4 @@ public class Area3DPtg extends OperandPtg implements AreaI { return true; } - - public int hashCode() - { - // TODO - hashCode seems to be unused - int result; - result = (int) field_1_index_extern_sheet; - result = 29 * result + (int) field_2_first_row; - result = 29 * result + (int) field_3_last_row; - result = 29 * result + (int) field_4_first_column; - result = 29 * result + (int) field_5_last_column; - return result; - } - - } diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaAPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaAPtg.java deleted file mode 100644 index e984b69f2..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/AreaAPtg.java +++ /dev/null @@ -1,68 +0,0 @@ - -/* ==================================================================== - 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. -==================================================================== */ - -/* - * AreaPtg.java - * - * Created on November 17, 2001, 9:30 PM - */ -package org.apache.poi.hssf.record.formula; - -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.BitField; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.hssf.util.AreaReference; -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.usermodel.Workbook; - -/** - * Specifies a rectangular area of cells A1:A4 for instance. - * @author Jason Height (jheight at chariot dot net dot au) - */ - -public final class AreaAPtg extends AreaPtg { - public final static short sid = 0x65; - - protected AreaAPtg() { - //Required for clone methods - } - - public AreaAPtg(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 AreaAPtg(RecordInputStream in) - { - super(in); - } - - public String getAreaPtgName() { - return "AreaAPtg"; - } - - public Object clone() { - AreaAPtg ptg = new AreaAPtg(); - ptg.setFirstRow(getFirstRow()); - ptg.setLastRow(getLastRow()); - ptg.setFirstColumnRaw(getFirstColumnRaw()); - ptg.setLastColumnRaw(getLastColumnRaw()); - ptg.setClass(ptgClass); - return ptg; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java index 182b8b43e..f1af9b68d 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java @@ -17,73 +17,40 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.BitField; - -import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.LittleEndian; /** * AreaErr - handles deleted cell area references. * * @author Daniel Noll (daniel at nuix dot com dot au) */ -public class AreaErrPtg extends AreaPtg -{ +public final class AreaErrPtg extends OperandPtg { public final static byte sid = 0x2b; - private AreaErrPtg() - { - //Required for clone methods - super(); - } - - public AreaErrPtg(RecordInputStream in) - { - super(in); - } - - public String toString() - { - StringBuffer buffer = new StringBuffer(); - - buffer.append("AreaErrPtg\n"); - buffer.append("firstRow = " + getFirstRow()).append("\n"); - buffer.append("lastRow = " + getLastRow()).append("\n"); - buffer.append("firstCol = " + getFirstColumn()).append("\n"); - buffer.append("lastCol = " + getLastColumn()).append("\n"); - buffer.append("firstColRowRel= " - + isFirstRowRelative()).append("\n"); - buffer.append("lastColRowRel = " - + isLastRowRelative()).append("\n"); - buffer.append("firstColRel = " + isFirstColRelative()).append("\n"); - buffer.append("lastColRel = " + isLastColRelative()).append("\n"); - return buffer.toString(); + public AreaErrPtg(RecordInputStream in) { + // 8 bytes unused: + in.readInt(); + in.readInt(); } public void writeBytes(byte [] array, int offset) { - super.writeBytes(array, offset); - array[offset] = (byte) (sid + ptgClass); + array[offset] = (byte) (sid + getPtgClass()); + LittleEndian.putInt(array, offset+1, 0); + LittleEndian.putInt(array, offset+5, 0); } - public String toFormulaString(Workbook book) - { + public String toFormulaString(Workbook book) { return "#REF!"; } - - public Object clone() - { - AreaErrPtg ptg = new AreaErrPtg(); - ptg.setFirstRow(getFirstRow()); - ptg.setFirstColumn(getFirstColumn()); - ptg.setLastRow(getLastRow()); - ptg.setLastColumn(getLastColumn()); - ptg.setFirstColRelative(isFirstColRelative()); - ptg.setLastColRelative(isLastColRelative()); - ptg.setFirstRowRelative(isFirstRowRelative()); - ptg.setLastRowRelative(isLastRowRelative()); - ptg.setClass(ptgClass); - return ptg; - } + + public byte getDefaultOperandClass() { + return Ptg.CLASS_REF; + } + + public int getSize() { + return 9; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaNAPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaNAPtg.java deleted file mode 100644 index 7667f65f5..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/AreaNAPtg.java +++ /dev/null @@ -1,53 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.ss.usermodel.Workbook; - -/** - * Specifies a rectangular area of cells A1:A4 for instance. - * @author Jason Height (jheight at chariot dot net dot au) - */ - -public final class AreaNAPtg extends AreaPtg -{ - public final static short sid = 0x6D; - - protected AreaNAPtg() { - //Required for clone methods - } - - public AreaNAPtg(RecordInputStream in) - { - super(in); - } - - public String getAreaPtgName() { - return "AreaNAPtg"; - } - - public String toFormulaString(Workbook book) - { - throw notImplemented(); - } - - public Object clone() { - throw notImplemented(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java index ee939a7fc..bf013838b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -16,49 +15,22 @@ limitations under the License. ==================================================================== */ -/* - * AreaPtg.java - * - * Created on November 17, 2001, 9:30 PM - */ package org.apache.poi.hssf.record.formula; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.BitField; - import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.hssf.util.AreaReference; -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.usermodel.Workbook; /** * Specifies a rectangular area of cells A1:A4 for instance. * @author Jason Height (jheight at chariot dot net dot au) */ +public final class AreaNPtg extends AreaPtgBase { + public final static short sid = 0x2D; -public final class AreaNPtg extends AreaPtg -{ - public final static short sid = 0x2D; + public AreaNPtg(RecordInputStream in) { + super(in); + } - protected AreaNPtg() { - //Required for clone methods - } - - public AreaNPtg(RecordInputStream in) - { - super(in); - } - - public String getAreaPtgName() { - return "AreaNPtg"; - } - - public String toFormulaString(Workbook book) - { - throw notImplemented(); - } - - public Object clone() { - throw notImplemented(); - } + protected byte getSid() { + return sid; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaNVPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaNVPtg.java deleted file mode 100644 index f24745f4a..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/AreaNVPtg.java +++ /dev/null @@ -1,52 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.ss.usermodel.Workbook; - -/** - * Specifies a rectangular area of cells A1:A4 for instance. - * @author andy - * @author Jason Height (jheight at chariot dot net dot au) - */ -public final class AreaNVPtg extends AreaPtg { - public final static short sid = 0x4D; - - protected AreaNVPtg() { - //Required for clone methods - } - - public AreaNVPtg(RecordInputStream in) - { - super(in); - } - - public String getAreaPtgName() { - return "AreaNVPtg"; - } - - public String toFormulaString(Workbook book) - { - throw notImplemented(); - } - - public Object clone() { - throw notImplemented(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java old mode 100644 new mode 100755 index f5f43e6cd..0839e5570 --- a/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java @@ -17,302 +17,25 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.BitField; -import org.apache.poi.util.BitFieldFactory; - -import org.apache.poi.hssf.util.AreaReference; -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.hssf.record.RecordInputStream; /** * Specifies a rectangular area of cells A1:A4 for instance. - * @author andy * @author Jason Height (jheight at chariot dot net dot au) */ -public class AreaPtg 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"); - } - +public final class AreaPtg extends AreaPtgBase { public final static short sid = 0x25; - private final static int SIZE = 9; - /** zero based, unsigned 16 bit */ - private int field_1_first_row; - /** zero based, unsigned 16 bit */ - private int field_2_last_row; - /** zero based, unsigned 8 bit */ - private int field_3_first_column; - /** zero based, unsigned 8 bit */ - private int field_4_last_column; - - 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 AreaPtg() { - //Required for clone methods + 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(RecordInputStream in) { + super(in); } - public AreaPtg(String arearef) { - AreaReference ar = new AreaReference(arearef); - CellReference firstCell = ar.getFirstCell(); - CellReference lastCell = ar.getLastCell(); - setFirstRow(firstCell.getRow()); - setFirstColumn(firstCell.getCol()); - setLastRow(lastCell.getRow()); - setLastColumn(lastCell.getCol()); - setFirstColRelative(!firstCell.isColAbsolute()); - setLastColRelative(!lastCell.isColAbsolute()); - setFirstRowRelative(!firstCell.isRowAbsolute()); - setLastRowRelative(!lastCell.isRowAbsolute()); - } - - public AreaPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, - boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) { - - checkColumnBounds(firstColumn); - checkColumnBounds(lastColumn); - checkRowBounds(firstRow); - checkRowBounds(lastRow); - setFirstRow(firstRow); - setLastRow(lastRow); - setFirstColumn(firstColumn); - setLastColumn(lastColumn); - setFirstRowRelative(firstRowRelative); - setLastRowRelative(lastRowRelative); - setFirstColRelative(firstColRelative); - setLastColRelative(lastColRelative); - } - - 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"); - } - } - - public AreaPtg(RecordInputStream in) - { - field_1_first_row = in.readUShort(); - field_2_last_row = in.readUShort(); - field_3_first_column = in.readUShort(); - field_4_last_column = in.readUShort(); - //System.out.println(toString()); - } - - public String getAreaPtgName() { - return "AreaPtg"; - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(getClass().getName()); - sb.append(" ["); - sb.append(AreaReference.formatAsString(this)); - sb.append("]"); - return sb.toString(); - } - - public void writeBytes(byte [] array, int offset) { - array[offset] = (byte) (sid + ptgClass); - LittleEndian.putShort(array,offset+1,(short)field_1_first_row); - LittleEndian.putShort(array,offset+3,(short)field_2_last_row); - LittleEndian.putShort(array,offset+5,(short)field_3_first_column); - LittleEndian.putShort(array,offset+7,(short)field_4_last_column); - } - - public int getSize() - { - return SIZE; - } - - /** - * @return the first row in the area - */ - public int getFirstRow() - { - return field_1_first_row; - } - - /** - * sets the first row - * @param rowIx number (0-based) - */ - public void setFirstRow(int rowIx) { - checkRowBounds(rowIx); - field_1_first_row = rowIx; - } - - /** - * @return last row in the range (x2 in x1,y1-x2,y2) - */ - public int getLastRow() - { - return field_2_last_row; - } - - /** - * @param rowIx last row number in the area - */ - public void setLastRow(int rowIx) { - checkRowBounds(rowIx); - field_2_last_row = rowIx; - } - - /** - * @return the first column number in the area. - */ - public int getFirstColumn() - { - return columnMask.getValue(field_3_first_column); - } - - /** - * @return the first column number + the options bit settings unstripped - */ - public short getFirstColumnRaw() - { - return (short) field_3_first_column; // TODO - } - - /** - * @return whether or not the first row is a relative reference or not. - */ - public boolean isFirstRowRelative() - { - return rowRelative.isSet(field_3_first_column); - } - - /** - * sets the first row to relative or not - * @param rel is relative or not. - */ - public void setFirstRowRelative(boolean rel) { - field_3_first_column=rowRelative.setBoolean(field_3_first_column,rel); - } - - /** - * @return isrelative first column to relative or not - */ - public boolean isFirstColRelative() - { - return colRelative.isSet(field_3_first_column); - } - - /** - * set whether the first column is relative - */ - public void setFirstColRelative(boolean rel) { - field_3_first_column=colRelative.setBoolean(field_3_first_column,rel); - } - - /** - * set the first column in the area - */ - public void setFirstColumn(int colIx) { - checkColumnBounds(colIx); - field_3_first_column=columnMask.setValue(field_3_first_column, colIx); - } - - /** - * set the first column irespective of the bitmasks - */ - public void setFirstColumnRaw(int column) - { - field_3_first_column = column; - } - - /** - * @return lastcolumn in the area - */ - public int getLastColumn() - { - return columnMask.getValue(field_4_last_column); - } - - /** - * @return last column and bitmask (the raw field) - */ - public short getLastColumnRaw() - { - return (short) field_4_last_column; - } - - /** - * @return last row relative or not - */ - public boolean isLastRowRelative() - { - return rowRelative.isSet(field_4_last_column); - } - - /** - * set whether the last row is relative or not - * @param rel true if the last row relative, else - * false - */ - public void setLastRowRelative(boolean rel) { - field_4_last_column=rowRelative.setBoolean(field_4_last_column,rel); - } - - /** - * @return lastcol relative or not - */ - public boolean isLastColRelative() - { - return colRelative.isSet(field_4_last_column); - } - - /** - * set whether the last column should be relative or not - */ - public void setLastColRelative(boolean rel) { - field_4_last_column=colRelative.setBoolean(field_4_last_column,rel); - } - - - /** - * set the last column in the area - */ - public void setLastColumn(int colIx) { - checkColumnBounds(colIx); - field_4_last_column=columnMask.setValue(field_4_last_column, colIx); - } - - /** - * set the last column irrespective of the bitmasks - */ - public void setLastColumnRaw(short column) - { - field_4_last_column = column; - } - - public String toFormulaString(Workbook book) { - return AreaReference.formatAsString(this); - } - - public byte getDefaultOperandClass() { - return Ptg.CLASS_REF; - } - - public Object clone() { - AreaPtg ptg = new AreaPtg(); - ptg.field_1_first_row = field_1_first_row; - ptg.field_2_last_row = field_2_last_row; - ptg.field_3_first_column = field_3_first_column; - ptg.field_4_last_column = field_4_last_column; - ptg.setClass(ptgClass); - return ptg; - } - + super(arearef); + } + protected byte getSid() { + return sid; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java b/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java new file mode 100644 index 000000000..9ac406b31 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java @@ -0,0 +1,286 @@ +/* ==================================================================== + 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.formula; + +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.BitField; +import org.apache.poi.util.BitFieldFactory; + +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.hssf.util.AreaReference; +import org.apache.poi.hssf.record.RecordInputStream; + +/** + * 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"); + } + + public final static short sid = 0x25; + private final static int SIZE = 9; + /** zero based, unsigned 16 bit */ + private int field_1_first_row; + /** zero based, unsigned 16 bit */ + private int field_2_last_row; + /** zero based, unsigned 8 bit */ + private int field_3_first_column; + /** zero based, unsigned 8 bit */ + private int field_4_last_column; + + 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(String arearef) { + AreaReference ar = new AreaReference(arearef); + CellReference firstCell = ar.getFirstCell(); + CellReference lastCell = ar.getLastCell(); + setFirstRow(firstCell.getRow()); + setFirstColumn(firstCell.getCol()); + setLastRow(lastCell.getRow()); + setLastColumn(lastCell.getCol()); + setFirstColRelative(!firstCell.isColAbsolute()); + setLastColRelative(!lastCell.isColAbsolute()); + setFirstRowRelative(!firstCell.isRowAbsolute()); + setLastRowRelative(!lastCell.isRowAbsolute()); + } + + protected AreaPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, + boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) { + + checkColumnBounds(firstColumn); + checkColumnBounds(lastColumn); + checkRowBounds(firstRow); + checkRowBounds(lastRow); + setFirstRow(firstRow); + setLastRow(lastRow); + setFirstColumn(firstColumn); + setLastColumn(lastColumn); + setFirstRowRelative(firstRowRelative); + setLastRowRelative(lastRowRelative); + setFirstColRelative(firstColRelative); + setLastColRelative(lastColRelative); + } + + 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 AreaPtgBase(RecordInputStream in) + { + field_1_first_row = in.readUShort(); + field_2_last_row = in.readUShort(); + field_3_first_column = in.readUShort(); + field_4_last_column = in.readUShort(); + } + + public final String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(getClass().getName()); + sb.append(" ["); + sb.append(AreaReference.formatAsString(this)); + sb.append("]"); + return sb.toString(); + } + protected abstract byte getSid(); + + public final void writeBytes(byte [] array, int offset) { + array[offset] = (byte) (getSid() + getPtgClass()); + LittleEndian.putShort(array,offset+1,(short)field_1_first_row); + LittleEndian.putShort(array,offset+3,(short)field_2_last_row); + LittleEndian.putShort(array,offset+5,(short)field_3_first_column); + LittleEndian.putShort(array,offset+7,(short)field_4_last_column); + } + + + public final int getSize() { + return SIZE; + } + + /** + * @return the first row in the area + */ + public final int getFirstRow() { + return field_1_first_row; + } + + /** + * sets the first row + * @param rowIx number (0-based) + */ + public final void setFirstRow(int rowIx) { + checkRowBounds(rowIx); + field_1_first_row = rowIx; + } + + /** + * @return last row in the range (x2 in x1,y1-x2,y2) + */ + public final int getLastRow() { + return field_2_last_row; + } + + /** + * @param rowIx last row number in the area + */ + public final void setLastRow(int rowIx) { + checkRowBounds(rowIx); + field_2_last_row = rowIx; + } + + /** + * @return the first column number in the area. + */ + public final int getFirstColumn() { + return columnMask.getValue(field_3_first_column); + } + + /** + * @return the first column number + the options bit settings unstripped + */ + public final short getFirstColumnRaw() { + return (short) field_3_first_column; // TODO + } + + /** + * @return whether or not the first row is a relative reference or not. + */ + public final boolean isFirstRowRelative() { + return rowRelative.isSet(field_3_first_column); + } + + /** + * sets the first row to relative or not + * @param rel is relative or not. + */ + public final void setFirstRowRelative(boolean rel) { + field_3_first_column=rowRelative.setBoolean(field_3_first_column,rel); + } + + /** + * @return isrelative first column to relative or not + */ + public final boolean isFirstColRelative() { + return colRelative.isSet(field_3_first_column); + } + + /** + * set whether the first column is relative + */ + public final void setFirstColRelative(boolean rel) { + field_3_first_column=colRelative.setBoolean(field_3_first_column,rel); + } + + /** + * set the first column in the area + */ + public final void setFirstColumn(int colIx) { + checkColumnBounds(colIx); + field_3_first_column=columnMask.setValue(field_3_first_column, colIx); + } + + /** + * set the first column irrespective of the bitmasks + */ + public final void setFirstColumnRaw(int column) { + field_3_first_column = column; + } + + /** + * @return lastcolumn in the area + */ + public final int getLastColumn() { + return columnMask.getValue(field_4_last_column); + } + + /** + * @return last column and bitmask (the raw field) + */ + public final short getLastColumnRaw() { + return (short) field_4_last_column; + } + + /** + * @return last row relative or not + */ + public final boolean isLastRowRelative() { + return rowRelative.isSet(field_4_last_column); + } + + /** + * set whether the last row is relative or not + * @param rel true if the last row relative, else + * false + */ + public final void setLastRowRelative(boolean rel) { + field_4_last_column=rowRelative.setBoolean(field_4_last_column,rel); + } + + /** + * @return lastcol relative or not + */ + public final boolean isLastColRelative() { + return colRelative.isSet(field_4_last_column); + } + + /** + * set whether the last column should be relative or not + */ + public final void setLastColRelative(boolean rel) { + field_4_last_column=colRelative.setBoolean(field_4_last_column,rel); + } + + /** + * set the last column in the area + */ + public final void setLastColumn(int colIx) { + checkColumnBounds(colIx); + field_4_last_column=columnMask.setValue(field_4_last_column, colIx); + } + + /** + * set the last column irrespective of the bitmasks + */ + public final void setLastColumnRaw(short column) { + field_4_last_column = column; + } + + public String toFormulaString(Workbook book) { + return AreaReference.formatAsString(this); + } + + public byte getDefaultOperandClass() { + return Ptg.CLASS_REF; + } +} diff --git a/src/java/org/apache/poi/hssf/record/formula/AreaVPtg.java b/src/java/org/apache/poi/hssf/record/formula/AreaVPtg.java deleted file mode 100644 index 77c02bf77..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/AreaVPtg.java +++ /dev/null @@ -1,71 +0,0 @@ - -/* ==================================================================== - 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. -==================================================================== */ - -/* - * AreaPtg.java - * - * Created on November 17, 2001, 9:30 PM - */ -package org.apache.poi.hssf.record.formula; - -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.BitField; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.hssf.util.AreaReference; -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.usermodel.Workbook; - -/** - * Specifies a rectangular area of cells A1:A4 for instance. - * @author Jason Height (jheight at chariot dot net dot au) - */ - -public final class AreaVPtg - extends AreaPtg -{ - public final static short sid = 0x45; - - protected AreaVPtg() { - //Required for clone methods - } - - public AreaVPtg(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 AreaVPtg(RecordInputStream in) - { - super(in); - } - - public String getAreaPtgName() { - return "AreaVPtg"; - } - - public Object clone() { - AreaVPtg ptg = new AreaVPtg(); - ptg.setFirstRow(getFirstRow()); - ptg.setLastRow(getLastRow()); - ptg.setFirstColumnRaw(getFirstColumnRaw()); - ptg.setLastColumnRaw(getLastColumnRaw()); - ptg.setClass(ptgClass); - return ptg; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java b/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java index cacce0485..371753007 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java @@ -35,29 +35,28 @@ import org.apache.poi.util.LittleEndian; * * @author Jason Height (jheight at chariot dot net dot au) */ -public class ArrayPtg extends Ptg { +public final class ArrayPtg extends Ptg { public static final byte sid = 0x20; private static final int RESERVED_FIELD_LEN = 7; // TODO - fix up field visibility and subclasses - protected byte[] field_1_reserved; + private byte[] field_1_reserved; + // data from these fields comes after the Ptg data of all tokens in current formula - protected short token_1_columns; - protected short token_2_rows; - protected Object[] token_3_arrayValues; + private short token_1_columns; + private short token_2_rows; + private Object[] token_3_arrayValues; - protected ArrayPtg() { - //Required for clone methods - } - - public ArrayPtg(RecordInputStream in) - { + public ArrayPtg(RecordInputStream in) { field_1_reserved = new byte[RESERVED_FIELD_LEN]; // TODO - add readFully method to RecordInputStream for(int i=0; i< RESERVED_FIELD_LEN; i++) { field_1_reserved[i] = in.readByte(); } } + public Object[] getTokenArrayValues() { + return (Object[]) token_3_arrayValues.clone(); + } public boolean isBaseToken() { return false; @@ -117,7 +116,7 @@ public class ArrayPtg extends Ptg { public void writeBytes(byte[] data, int offset) { - LittleEndian.putByte(data, offset + 0, sid + ptgClass); + LittleEndian.putByte(data, offset + 0, sid + getPtgClass()); System.arraycopy(field_1_reserved, 0, data, offset+1, RESERVED_FIELD_LEN); } @@ -190,13 +189,9 @@ public class ArrayPtg extends Ptg { } public Object clone() { - ArrayPtg ptg = new ArrayPtg(); + ArrayPtg ptg = (ArrayPtg) super.clone(); ptg.field_1_reserved = (byte[]) field_1_reserved.clone(); - - ptg.token_1_columns = token_1_columns; - ptg.token_2_rows = token_2_rows; ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone(); - ptg.setClass(ptgClass); return ptg; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java b/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java deleted file mode 100644 index 5be866e96..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java +++ /dev/null @@ -1,48 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; - -/** - * ArrayPtgA - handles arrays - * - * @author Jason Height (jheight at chariot dot net dot au) - */ -public final class ArrayPtgA extends ArrayPtg { - public final static byte sid = 0x60; - - private ArrayPtgA() { - //Required for clone methods - } - - public ArrayPtgA(RecordInputStream in) { - super(in); - } - - public Object clone() { - ArrayPtgA ptg = new ArrayPtgA(); - ptg.field_1_reserved = (byte[]) field_1_reserved.clone(); - - ptg.token_1_columns = token_1_columns; - ptg.token_2_rows = token_2_rows; - ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone(); - ptg.setClass(ptgClass); - return ptg; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java b/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java deleted file mode 100644 index ba955654a..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java +++ /dev/null @@ -1,54 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; - -/** - * ArrayPtg - handles arrays - * - * The ArrayPtg is a little weird, the size of the Ptg when parsing initially only - * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows. - * 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 ArrayPtgV extends ArrayPtg { - public final static byte sid = 0x40; - - private ArrayPtgV() { - //Required for clone methods - } - - public ArrayPtgV(RecordInputStream in) { - super(in); - } - - public Object clone() { - ArrayPtgV ptg = new ArrayPtgV(); - ptg.field_1_reserved = (byte[]) field_1_reserved.clone(); - - ptg.token_1_columns = token_1_columns; - ptg.token_2_rows = token_2_rows; - ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone(); - ptg.setClass(ptgClass); - return ptg; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/BoolPtg.java b/src/java/org/apache/poi/hssf/record/formula/BoolPtg.java index 401bf4df0..3d9c49660 100644 --- a/src/java/org/apache/poi/hssf/record/formula/BoolPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/BoolPtg.java @@ -30,11 +30,7 @@ import org.apache.poi.hssf.record.RecordInputStream; public final class BoolPtg extends ScalarConstantPtg { public final static int SIZE = 2; public final static byte sid = 0x1d; - private boolean field_1_value; - - private BoolPtg() { - //Required for clone methods - } + private final boolean field_1_value; public BoolPtg(RecordInputStream in) { @@ -46,11 +42,6 @@ public final class BoolPtg extends ScalarConstantPtg { field_1_value = (formulaToken.equals("TRUE")); } - public void setValue(boolean value) - { - field_1_value = value; - } - public boolean getValue() { return field_1_value; @@ -71,10 +62,4 @@ public final class BoolPtg extends ScalarConstantPtg { { return field_1_value ? "TRUE" : "FALSE"; } - - public Object clone() { - BoolPtg ptg = new BoolPtg(); - ptg.field_1_value = field_1_value; - return ptg; - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/ConcatPtg.java b/src/java/org/apache/poi/hssf/record/formula/ConcatPtg.java index 6473c7f98..28cca4f2e 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ConcatPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ConcatPtg.java @@ -17,54 +17,29 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * * @author andy * @author Jason Height (jheight at chariot dot net dot au) */ public final class ConcatPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x08; private final static String CONCAT = "&"; - public ConcatPtg(RecordInputStream in) - { - // No contents + public static final ValueOperatorPtg instance = new ConcatPtg(); + + private ConcatPtg() { + // enforce singleton } - public ConcatPtg() { - + protected byte getSid() { + return sid; } - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - - public String toFormulaString(Workbook book) - { - return CONCAT; - } - public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); @@ -74,9 +49,4 @@ public final class ConcatPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new ConcatPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/DividePtg.java b/src/java/org/apache/poi/hssf/record/formula/DividePtg.java index 960ff9032..fd5f86aab 100644 --- a/src/java/org/apache/poi/hssf/record/formula/DividePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/DividePtg.java @@ -17,66 +17,34 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * 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 int SIZE = 1; public final static byte sid = 0x06; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new DividePtg(); - public DividePtg() - { + private DividePtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public DividePtg(RecordInputStream in) - { - - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - public String toFormulaString(Workbook book) - { - return "/"; - } - public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); buffer.append(operands[ 0 ]); - buffer.append(toFormulaString((Workbook)null)); + buffer.append("/"); buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - DividePtg ptg = new DividePtg(); - return ptg; - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/EqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/EqualPtg.java index 9ae08426b..7fbd17330 100644 --- a/src/java/org/apache/poi/hssf/record/formula/EqualPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/EqualPtg.java @@ -17,67 +17,34 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * * @author andy */ public final class EqualPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x0b; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new EqualPtg(); - public EqualPtg() - { + private EqualPtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public EqualPtg(RecordInputStream in) - { - - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - - public String toFormulaString(Workbook book) - { - return "="; - } public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); buffer.append(operands[ 0 ]); - buffer.append(toFormulaString((Workbook)null)); + buffer.append("="); buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new EqualPtg(); - } - - } diff --git a/src/java/org/apache/poi/hssf/record/formula/ErrPtg.java b/src/java/org/apache/poi/hssf/record/formula/ErrPtg.java index 9d81e3bc2..27a2b29de 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ErrPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ErrPtg.java @@ -47,7 +47,7 @@ public final class ErrPtg extends ScalarConstantPtg { public static final short sid = 0x1c; private static final int SIZE = 2; - private int field_1_error_code; + private final int field_1_error_code; /** Creates new ErrPtg */ @@ -64,7 +64,7 @@ public final class ErrPtg extends ScalarConstantPtg { public void writeBytes(byte [] array, int offset) { - array[offset] = (byte) (sid + ptgClass); + array[offset] = (byte) (sid + getPtgClass()); array[offset + 1] = (byte)field_1_error_code; } @@ -76,10 +76,6 @@ public final class ErrPtg extends ScalarConstantPtg { return SIZE; } - public Object clone() { - return new ErrPtg(field_1_error_code); - } - public int getErrorCode() { return field_1_error_code; } diff --git a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java index 91f4baf3b..62a887850 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -30,20 +29,11 @@ import org.apache.poi.util.LittleEndian; * @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 short field_1_first_row; - private short field_2_first_col; - - /** Creates new ExpPtg */ - - public ExpPtg() - { - } - - /** Creates new ExpPtg */ + private final short field_1_first_row; + private final short field_2_first_col; public ExpPtg(RecordInputStream in) { @@ -83,12 +73,4 @@ public final class ExpPtg extends ControlPtg { buffer.append("col = ").append(getColumn()).append("\n"); return buffer.toString(); } - - public Object clone() { - ExpPtg result = new ExpPtg(); - result.field_1_first_row = field_1_first_row; - result.field_2_first_col = field_2_first_col; - return result; - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java b/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java index cea44ed43..c0034b24f 100644 --- a/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java @@ -56,7 +56,7 @@ public final class FuncPtg extends AbstractFunctionPtg { } public void writeBytes(byte[] array, int offset) { - array[offset+0]= (byte) (sid + ptgClass); + array[offset+0]= (byte) (sid + getPtgClass()); LittleEndian.putShort(array,offset+1,field_2_fnc_index); } @@ -64,12 +64,6 @@ public final class FuncPtg extends AbstractFunctionPtg { return numParams; } - public Object clone() { - FuncPtg ptg = new FuncPtg(field_2_fnc_index); - ptg.setClass(ptgClass); - return ptg; - } - public int getSize() { return SIZE; } diff --git a/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java b/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java index e3d2e7731..fd3546250 100644 --- a/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java @@ -30,11 +30,7 @@ public final class FuncVarPtg extends AbstractFunctionPtg{ public final static byte sid = 0x22; private final static int SIZE = 4; - private FuncVarPtg() { - //Required for clone methods - } - - /**Creates new function pointer from a byte array + /**Creates new function pointer from a byte array * usually called while reading an excel file. */ public FuncVarPtg(RecordInputStream in) { @@ -69,7 +65,7 @@ public final class FuncVarPtg extends AbstractFunctionPtg{ } public void writeBytes(byte[] array, int offset) { - array[offset+0]=(byte) (sid + ptgClass); + array[offset+0]=(byte) (sid + getPtgClass()); array[offset+1]=field_1_num_args; LittleEndian.putShort(array,offset+2,field_2_fnc_index); } @@ -78,14 +74,6 @@ public final class FuncVarPtg extends AbstractFunctionPtg{ return field_1_num_args; } - public Object clone() { - FuncVarPtg ptg = new FuncVarPtg(); - ptg.field_1_num_args = field_1_num_args; - ptg.field_2_fnc_index = field_2_fnc_index; - ptg.setClass(ptgClass); - return ptg; - } - public int getSize() { return SIZE; } diff --git a/src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java index 91b9713a8..f46191ed8 100755 --- a/src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java @@ -17,8 +17,6 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** * PTG class to implement greater or equal to @@ -29,56 +27,28 @@ public final class GreaterEqualPtg extends ValueOperatorPtg { public final static int SIZE = 1; public final static byte sid = 0x0c; - /** Creates new GreaterEqualPtg */ + public static final ValueOperatorPtg instance = new GreaterEqualPtg(); - public GreaterEqualPtg() - { + private GreaterEqualPtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public GreaterEqualPtg(RecordInputStream in) - { - - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - public String toFormulaString(Workbook book) - { - return ">="; - } - public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); buffer.append(operands[ 0 ]); - buffer.append(toFormulaString((Workbook)null)); + buffer.append(">="); buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new GreaterEqualPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/GreaterThanPtg.java b/src/java/org/apache/poi/hssf/record/formula/GreaterThanPtg.java index 9bc83e569..248cf6ff4 100644 --- a/src/java/org/apache/poi/hssf/record/formula/GreaterThanPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/GreaterThanPtg.java @@ -17,81 +17,33 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** * Greater than operator PTG ">" * @author Cameron Riley (criley at ekmail.com) */ public final class GreaterThanPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x0D; private final static String GREATERTHAN = ">"; - /** - * Constructor. Creates new GreaterThanPtg - */ - public GreaterThanPtg() - { - //deliberately empty - } + public static final ValueOperatorPtg instance = new GreaterThanPtg(); - /** - * Constructor. Create a new GreaterThanPtg. - * @param in the RecordInputstream to read the record from - */ - public GreaterThanPtg(RecordInputStream in) - { - //deliberately empty + private GreaterThanPtg() { + // enforce singleton } - /** - * Write the sid to an array - * @param array the array of bytes to write the sid to - * @param offset the offset to add the sid to - */ - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - /** - * Get the size of the sid - * @return int the size of the sid in terms of byte additions to an array - */ - public int getSize() - { - return SIZE; - } - - /** - * Get the type of PTG for Greater Than - * @return int the identifier for the type - */ - public int getType() - { - return TYPE_BINARY; + protected byte getSid() { + return sid; } /** * Get the number of operands for the Less than operator * @return int the number of operands */ - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - /** - * Implementation of method from Ptg - * @param book the Sheet References - */ - public String toFormulaString(Workbook book) - { - return this.GREATERTHAN; - } - /** * Implementation of method from OperationsPtg * @param operands a String array of operands @@ -102,17 +54,8 @@ public final class GreaterThanPtg extends ValueOperatorPtg { StringBuffer buffer = new StringBuffer(); buffer.append(operands[ 0 ]); - buffer.append(this.GREATERTHAN); + buffer.append(GREATERTHAN); buffer.append(operands[ 1 ]); return buffer.toString(); } - - /** - * Implementation of clone method from Object - * @return Object a clone of this class as an Object - */ - public Object clone() - { - return new GreaterThanPtg(); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/IntPtg.java b/src/java/org/apache/poi/hssf/record/formula/IntPtg.java index 673ce4fad..609b3ea45 100644 --- a/src/java/org/apache/poi/hssf/record/formula/IntPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/IntPtg.java @@ -43,13 +43,12 @@ public final class IntPtg extends ScalarConstantPtg { public final static int SIZE = 3; public final static byte sid = 0x1e; - private int field_1_value; + private final int field_1_value; public IntPtg(RecordInputStream in) { this(in.readUShort()); } - public IntPtg(int value) { if(!isInRange(value)) { throw new IllegalArgumentException("value is out of range: " + value); @@ -61,7 +60,6 @@ public final class IntPtg extends ScalarConstantPtg { return field_1_value; } - public void writeBytes(byte [] array, int offset) { array[ offset + 0 ] = sid; @@ -76,9 +74,6 @@ public final class IntPtg extends ScalarConstantPtg { return String.valueOf(getValue()); } - public Object clone() { - return new IntPtg(field_1_value); - } public String toString() { StringBuffer sb = new StringBuffer(64); sb.append(getClass().getName()).append(" ["); diff --git a/src/java/org/apache/poi/hssf/record/formula/IntersectionPtg.java b/src/java/org/apache/poi/hssf/record/formula/IntersectionPtg.java index e7a0ea7ce..d939e0570 100644 --- a/src/java/org/apache/poi/hssf/record/formula/IntersectionPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/IntersectionPtg.java @@ -18,7 +18,6 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** * @author Daniel Noll (daniel at nuix dot com dot au) @@ -26,14 +25,10 @@ import org.apache.poi.hssf.record.RecordInputStream; public final class IntersectionPtg extends OperationPtg { public final static byte sid = 0x0f; + public static final OperationPtg instance = new IntersectionPtg(); - public IntersectionPtg() - { - } - - public IntersectionPtg(RecordInputStream in) - { - // doesn't need anything + private IntersectionPtg() { + // enforce singleton } public final boolean isBaseToken() { @@ -50,16 +45,6 @@ public final class IntersectionPtg extends OperationPtg { array[ offset + 0 ] = sid; } - public Object clone() - { - return new IntersectionPtg(); - } - - public int getType() - { - return TYPE_BINARY; - } - /** Implementation of method from Ptg */ public String toFormulaString(Workbook book) { diff --git a/src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java index f6e4919c4..99070e192 100755 --- a/src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java @@ -19,8 +19,6 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** @@ -29,58 +27,27 @@ import org.apache.poi.hssf.record.RecordInputStream; * @author fred at stsci dot edu */ public final class LessEqualPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x0a; - /** - * Creates new LessEqualPtg - */ - public LessEqualPtg() - { + public static final ValueOperatorPtg instance = new LessEqualPtg(); + private LessEqualPtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public LessEqualPtg( RecordInputStream in ) - { - // doesn't need anything - } - - public void writeBytes( byte[] array, int offset ) - { - array[offset + 0] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - public String toFormulaString( Workbook book ) - { - return "<="; - } - - public String toFormulaString( String[] operands ) - { + public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); buffer.append( operands[0] ); - buffer.append( toFormulaString( (Workbook) null ) ); + buffer.append("<="); buffer.append( operands[1] ); return buffer.toString(); } - - public Object clone() - { - return new LessEqualPtg(); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/LessThanPtg.java b/src/java/org/apache/poi/hssf/record/formula/LessThanPtg.java index 03241ef37..f2fd06fe2 100644 --- a/src/java/org/apache/poi/hssf/record/formula/LessThanPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/LessThanPtg.java @@ -17,9 +17,6 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * Less than operator PTG "<". The SID is taken from the * Openoffice.orgs Documentation of the Excel File Format, @@ -27,79 +24,31 @@ import org.apache.poi.hssf.record.RecordInputStream; * @author Cameron Riley (criley at ekmail.com) */ public final class LessThanPtg extends ValueOperatorPtg { - /** the size of the Ptg */ - public final static int SIZE = 1; - /** the sid for the less than operator as hex */ public final static byte sid = 0x09; /** identifier for LESS THAN char */ private final static String LESSTHAN = "<"; - /** - * Constructor. Creates new LessThanPtg - */ - public LessThanPtg() - { - //deliberately empty - } + public static final ValueOperatorPtg instance = new LessThanPtg(); - /** - * Constructor. Create a new LessThanPtg. - * @param in the RecordInputstream to read the record from - */ - public LessThanPtg(RecordInputStream in) - { - //deliberately empty + private LessThanPtg() { + // enforce singleton } - /** - * Write the sid to an array - * @param array the array of bytes to write the sid to - * @param offset the offset to add the sid to - */ - public void writeBytes(byte[] array, int offset) - { - array[ offset + 0 ] = sid; - } - - /** - * Get the size of the sid - * @return int the size of the sid in terms of byte additions to an array - */ - public int getSize() - { - return SIZE; - } - - /** - * Get the type of PTG for Less Than - * @return int the identifier for the type - */ - public int getType() - { - return TYPE_BINARY; + protected byte getSid() { + return sid; } /** * Get the number of operands for the Less than operator * @return int the number of operands */ - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - /** - * Implementation of method from Ptg - * @param book the Sheet References - */ - public String toFormulaString(Workbook book) - { - return this.LESSTHAN; - } - - /** + /** * Implementation of method from OperationsPtg * @param operands a String array of operands * @return String the Formula as a String @@ -108,18 +57,8 @@ public final class LessThanPtg extends ValueOperatorPtg { { StringBuffer buffer = new StringBuffer(); buffer.append(operands[ 0 ]); - buffer.append(this.LESSTHAN); + buffer.append(LESSTHAN); buffer.append(operands[ 1 ]); return buffer.toString(); } - - /** - * Implementation of clone method from Object - * @return Object a clone of this class as an Object - */ - public Object clone() - { - return new LessThanPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/MemAreaPtg.java b/src/java/org/apache/poi/hssf/record/formula/MemAreaPtg.java index a2e075c22..10ce43789 100644 --- a/src/java/org/apache/poi/hssf/record/formula/MemAreaPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/MemAreaPtg.java @@ -64,7 +64,7 @@ public class MemAreaPtg extends OperandPtg { public void writeBytes(byte [] array, int offset) { - array[offset] = (byte) (sid + ptgClass); + array[offset] = (byte) (sid + getPtgClass()); LittleEndian.putInt(array, offset + 1, field_1_reserved); LittleEndian.putShort(array, offset + 5, field_2_subex_len); } @@ -79,12 +79,7 @@ public class MemAreaPtg extends OperandPtg { return ""; // TODO: Not sure how to format this. -- DN } - public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} - - public Object clone() { - MemAreaPtg ptg = new MemAreaPtg(); - ptg.field_1_reserved = field_1_reserved; - ptg.field_2_subex_len = field_2_subex_len; - return ptg; + public byte getDefaultOperandClass() { + return Ptg.CLASS_VALUE; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java b/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java index 4c9156a90..e6afeae95 100644 --- a/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -16,17 +15,10 @@ limitations under the License. ==================================================================== */ - -/* - * MemErrPtg.java - * - * Created on November 21, 2001, 8:46 AM - */ package org.apache.poi.hssf.record.formula; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ss.usermodel.Workbook; /** * @@ -35,9 +27,7 @@ import org.apache.poi.hssf.record.RecordInputStream; * @author Daniel Noll (daniel at nuix dot com dot au) */ -public class MemErrPtg - extends MemAreaPtg -{ +public final class MemErrPtg extends MemAreaPtg { public final static short sid = 0x27; /** Creates new MemErrPtg */ @@ -46,26 +36,17 @@ public class MemErrPtg { } - public MemErrPtg(RecordInputStream in) - { + public MemErrPtg(RecordInputStream in) { super(in); } - public void writeBytes(byte [] array, int offset) - { + public void writeBytes(byte [] array, int offset) { super.writeBytes(array, offset); - array[offset] = (byte) (sid + ptgClass); + array[offset] = (byte) (sid + getPtgClass()); } public String toFormulaString(Workbook book) { return "ERR#"; } - - public Object clone() { - MemErrPtg ptg = new MemErrPtg(); - ptg.setReserved(getReserved()); - ptg.setSubexpressionLength(getSubexpressionLength()); - return ptg; - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/MemFuncPtg.java b/src/java/org/apache/poi/hssf/record/formula/MemFuncPtg.java index a351cbc9a..26fe637ba 100644 --- a/src/java/org/apache/poi/hssf/record/formula/MemFuncPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/MemFuncPtg.java @@ -15,12 +15,6 @@ limitations under the License. ==================================================================== */ - -/* - * Ptg.java - * - * Created on October 28, 2001, 6:30 PM - */ package org.apache.poi.hssf.record.formula; import org.apache.poi.util.LittleEndian; @@ -30,25 +24,23 @@ import org.apache.poi.hssf.record.RecordInputStream; /** * @author Glen Stampoultzis (glens at apache.org) */ -public class MemFuncPtg extends OperandPtg { +public final class MemFuncPtg extends OperandPtg { public final static byte sid = 0x29; - private short field_1_len_ref_subexpression = 0; - - public MemFuncPtg() - { - //Required for clone methods - } + private final int field_1_len_ref_subexpression; /**Creates new function pointer from a byte array * usually called while reading an excel file. */ - public MemFuncPtg( RecordInputStream in ) - { - field_1_len_ref_subexpression = in.readShort(); + public MemFuncPtg(RecordInputStream in) { + this(in.readUShort()); } - public int getSize() + public MemFuncPtg(int subExprLen) { + field_1_len_ref_subexpression = subExprLen; + } + + public int getSize() { return 3; } @@ -56,7 +48,7 @@ public class MemFuncPtg extends OperandPtg { public void writeBytes( byte[] array, int offset ) { array[offset + 0] = sid ; - LittleEndian.putShort( array, offset + 1, (short)field_1_len_ref_subexpression ); + LittleEndian.putUShort( array, offset + 1, field_1_len_ref_subexpression ); } public String toFormulaString(Workbook book) @@ -66,7 +58,7 @@ public class MemFuncPtg extends OperandPtg { public byte getDefaultOperandClass() { - return 0; + return Ptg.CLASS_REF; } public int getNumberOfOperands() @@ -74,21 +66,8 @@ public class MemFuncPtg extends OperandPtg { return field_1_len_ref_subexpression; } - public Object clone() - { - MemFuncPtg ptg = new MemFuncPtg(); - ptg.field_1_len_ref_subexpression = this.field_1_len_ref_subexpression; - return ptg; - } - public int getLenRefSubexpression() { return field_1_len_ref_subexpression; } - - public void setLenRefSubexpression(int len) - { - field_1_len_ref_subexpression = (short)len; - } - } \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/formula/MissingArgPtg.java b/src/java/org/apache/poi/hssf/record/formula/MissingArgPtg.java index 890f9e895..19f56cff7 100644 --- a/src/java/org/apache/poi/hssf/record/formula/MissingArgPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/MissingArgPtg.java @@ -18,7 +18,6 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** * Missing Function Arguments @@ -31,16 +30,10 @@ public final class MissingArgPtg extends ScalarConstantPtg { private final static int SIZE = 1; public final static byte sid = 0x16; - public MissingArgPtg() + public static final Ptg instance = new MissingArgPtg(); + private MissingArgPtg() { } - - public MissingArgPtg(RecordInputStream in) - { - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) { @@ -51,15 +44,9 @@ public final class MissingArgPtg extends ScalarConstantPtg { { return SIZE; } - public String toFormulaString(Workbook book) { return " "; } - - public Object clone() { - return new MissingArgPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java b/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java index 1c5c80eab..f627a9190 100644 --- a/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java @@ -14,83 +14,37 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ -package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; +package org.apache.poi.hssf.record.formula; /** * Implements the standard mathmatical multiplication - * * @author Andrew C. Oliver (acoliver at apache dot org) * @author Jason Height (jheight at chariot dot net dot au) */ - public final class MultiplyPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x05; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new MultiplyPtg(); - public MultiplyPtg() - { - } - - public MultiplyPtg(RecordInputStream in) - { - - // doesn't need anything + private MultiplyPtg() { + // enforce singleton } - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; + protected byte getSid() { + return sid; } - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - - public int getStringLength() { - return 1; - } - - - public String toFormulaString(Workbook book) - { - return "*"; - } - - public String toFormulaString(Ptg [] operands) - { - StringBuffer buffer = new StringBuffer(); - - buffer.append(operands[ 0 ].toFormulaString((Workbook)null)); - buffer.append("*"); - buffer.append(operands[ 1 ].toFormulaString((Workbook)null)); - return buffer.toString(); - } public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); buffer.append(operands[ 0 ]); - buffer.append(toFormulaString((Workbook)null)); + buffer.append("*"); buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new MultiplyPtg(); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/NamePtg.java b/src/java/org/apache/poi/hssf/record/formula/NamePtg.java index 22215e2ec..a29ae5541 100644 --- a/src/java/org/apache/poi/hssf/record/formula/NamePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/NamePtg.java @@ -33,12 +33,6 @@ public final class NamePtg extends OperandPtg { /** one-based index to defined name record */ private short field_1_label_index; private short field_2_zero; // reserved must be 0 - boolean xtra=false; - - - private NamePtg() { - //Required for clone methods - } /** * Creates new NamePtg and sets its name index to that of the corresponding defined name record @@ -68,12 +62,9 @@ public final class NamePtg extends OperandPtg { /** Creates new NamePtg */ - public NamePtg(RecordInputStream in) - { - //field_1_ixti = LittleEndian.getShort(data, offset); + public NamePtg(RecordInputStream in) { field_1_label_index = in.readShort(); field_2_zero = in.readShort(); - //if (data[offset+6]==0) xtra=true; } /** @@ -83,15 +74,13 @@ public final class NamePtg extends OperandPtg { return field_1_label_index-1; // convert to zero based } - public void writeBytes(byte [] array, int offset) - { - array[offset+0]= (byte) (sid + ptgClass); + public void writeBytes(byte [] array, int offset) { + array[offset+0]= (byte) (sid + getPtgClass()); LittleEndian.putShort(array,offset+1,field_1_label_index); LittleEndian.putShort(array,offset+3, field_2_zero); } - public int getSize() - { + public int getSize() { return SIZE; } @@ -100,12 +89,7 @@ public final class NamePtg extends OperandPtg { return book.getNameName(field_1_label_index - 1); } - public byte getDefaultOperandClass() {return Ptg.CLASS_REF;} - - public Object clone() { - NamePtg ptg = new NamePtg(); - ptg.field_1_label_index = field_1_label_index; - ptg.field_2_zero = field_2_zero; - return ptg; - } + public byte getDefaultOperandClass() { + return Ptg.CLASS_REF; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/NameXPtg.java b/src/java/org/apache/poi/hssf/record/formula/NameXPtg.java index 6d98ef2eb..0a99ff140 100644 --- a/src/java/org/apache/poi/hssf/record/formula/NameXPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/NameXPtg.java @@ -33,31 +33,20 @@ public final class NameXPtg extends OperandPtg { private short field_3_reserved; // reserved must be 0 - private NameXPtg() { - //Required for clone methods - } - - /** Creates new NamePtg */ - - public NameXPtg(RecordInputStream in) - { + public NameXPtg(RecordInputStream in) { field_1_ixals = in.readShort(); field_2_ilbl = in.readShort(); field_3_reserved = in.readShort(); - - //field_2_reserved = LittleEndian.getByteArray(data, offset + 12,12); } - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = (byte)(sid + ptgClass); + public void writeBytes(byte [] array, int offset) { + array[ offset + 0 ] = (byte)(sid + getPtgClass()); LittleEndian.putShort(array, offset + 1, field_1_ixals); LittleEndian.putShort(array,offset+3, field_2_ilbl); LittleEndian.putShort(array, offset + 5, field_3_reserved); } - public int getSize() - { + public int getSize() { return SIZE; } @@ -67,14 +56,7 @@ public final class NameXPtg extends OperandPtg { return book.resolveNameXText(field_1_ixals, field_2_ilbl-1); } - public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} - - public Object clone() { - NameXPtg ptg = new NameXPtg(); - ptg.field_1_ixals = field_1_ixals; - ptg.field_3_reserved = field_3_reserved; - ptg.field_2_ilbl = field_2_ilbl; - ptg.setClass(ptgClass); - return ptg; - } + public byte getDefaultOperandClass() { + return Ptg.CLASS_VALUE; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java index 95b68e87d..62739dbd7 100755 --- a/src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -18,70 +17,36 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * Ptg class to implement not equal * * @author fred at stsci dot edu */ public final class NotEqualPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x0e; - /** - * Creates new NotEqualPtg - */ - public NotEqualPtg() - { + public static final ValueOperatorPtg instance = new NotEqualPtg(); + + private NotEqualPtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public NotEqualPtg( RecordInputStream in ) - { - // doesn't need anything - } - - public void writeBytes( byte[] array, int offset ) - { - array[offset + 0] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - public String toFormulaString( Workbook book ) - { - return "<>"; - } - - public String toFormulaString( String[] operands ) - { + public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); buffer.append( operands[0] ); - buffer.append( toFormulaString( (Workbook) null ) ); + buffer.append("<>"); buffer.append( operands[1] ); return buffer.toString(); } - - public Object clone() - { - return new NotEqualPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java b/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java index a6d9e9259..dc28e705a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java @@ -31,16 +31,12 @@ import org.apache.poi.hssf.record.RecordInputStream; public final class NumberPtg extends ScalarConstantPtg { public final static int SIZE = 9; public final static byte sid = 0x1f; - private double field_1_value; - - private NumberPtg() { - //Required for clone methods - } + private final double field_1_value; /** Create a NumberPtg from a byte array read from disk */ public NumberPtg(RecordInputStream in) { - setValue(in.readDouble()); + field_1_value = in.readDouble(); } /** Create a NumberPtg from a string representation of the number @@ -49,13 +45,7 @@ public final class NumberPtg extends ScalarConstantPtg { * @param value : String representation of a floating point number */ public NumberPtg(String value) { - setValue(Double.parseDouble(value)); - } - - - public void setValue(double value) - { - field_1_value = value; + field_1_value = Double.parseDouble(value); } @@ -79,10 +69,4 @@ public final class NumberPtg extends ScalarConstantPtg { { return "" + getValue(); } - - public Object clone() { - NumberPtg ptg = new NumberPtg(); - ptg.field_1_value = field_1_value; - return ptg; - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java index 77df6b3b0..085fa1e16 100644 --- a/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java @@ -17,21 +17,15 @@ package org.apache.poi.hssf.record.formula; - - /** * defines a Ptg that is an operation instead of an operand * @author andy */ - -public abstract class OperationPtg extends Ptg -{ +public abstract class OperationPtg extends Ptg { public final static int TYPE_UNARY = 0; public final static int TYPE_BINARY = 1; public final static int TYPE_FUNCTION = 2; - public abstract int getType(); - /** * returns a string representation of the operations * the length of the input array should equal the number returned by @@ -45,6 +39,12 @@ public abstract class OperationPtg extends Ptg */ public abstract int getNumberOfOperands(); - public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} + public byte getDefaultOperandClass() { + return Ptg.CLASS_VALUE; + } + public final int getType() { + // TODO remove "int getType();" from Eval hierarchy + throw new RuntimeException("remove this method"); + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java b/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java index 7781d061c..67bb85bfe 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java @@ -37,17 +37,10 @@ public final class ParenthesisPtg extends ControlPtg { private final static int SIZE = 1; public final static byte sid = 0x15; - public ParenthesisPtg() - { + public static final ControlPtg instance = new ParenthesisPtg(); + private ParenthesisPtg() { + // enforce singleton } - - public ParenthesisPtg(RecordInputStream in) - { - - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) { @@ -68,9 +61,4 @@ public final class ParenthesisPtg extends ControlPtg { public String toFormulaString(String[] operands) { return "("+operands[0]+")"; } - - public Object clone() { - return new ParenthesisPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/PercentPtg.java b/src/java/org/apache/poi/hssf/record/formula/PercentPtg.java index a8d6450b4..9dd7bd2be 100644 --- a/src/java/org/apache/poi/hssf/record/formula/PercentPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/PercentPtg.java @@ -1,4 +1,3 @@ - /* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with @@ -16,68 +15,33 @@ limitations under the License. ==================================================================== */ -/* - * PercentPtg.java - * - * Created on March 29, 2006, 9:23 PM - */ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * 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 = "%"; - /** Creates new PercentPtg */ + public static final ValueOperatorPtg instance = new PercentPtg(); - public PercentPtg() - { - } - - public PercentPtg(RecordInputStream in) - { - - // doesn't need anything + private PercentPtg() { + // enforce singleton } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; + protected byte getSid() { + return sid; } - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_UNARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 1; } - - /** Implementation of method from Ptg */ - public String toFormulaString(Workbook book) - { - return "%"; - } - /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); @@ -85,9 +49,4 @@ public final class PercentPtg extends ValueOperatorPtg { buffer.append(PERCENT); return buffer.toString(); } - - public Object clone() { - return new PercentPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java b/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java index dbd0f2858..478b12fac 100644 --- a/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java @@ -17,53 +17,26 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * * @author andy * @author Jason Height (jheight at chariot dot net dot au) */ public final class PowerPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x07; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new PowerPtg(); - public PowerPtg() - { + private PowerPtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public PowerPtg(RecordInputStream in) - { - - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { - return 2; - } - - public String toFormulaString(Workbook book) - { - return "^"; + public int getNumberOfOperands() { + return 2; // TODO - 2 seems wrong (Jun 2008). Maybe this method is not relevant } public String toFormulaString(String[] operands) { @@ -71,13 +44,8 @@ public final class PowerPtg extends ValueOperatorPtg { buffer.append(operands[ 0 ]); - buffer.append(toFormulaString((Workbook)null)); + buffer.append("^"); buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new PowerPtg(); - } - } 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 7819c35bc..666b83cfa 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -17,226 +17,243 @@ package org.apache.poi.hssf.record.formula; -import java.util.List; import java.util.ArrayList; +import java.util.List; import java.util.Stack; -import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ss.usermodel.Workbook; /** + * Ptg represents a syntactic token in a formula. 'PTG' is an acronym for + * 'parse thing'. Originally, the name referred to the single + * byte identifier at the start of the token, but in POI, Ptg encapsulates + * the whole formula token (initial byte + value data). + *

+ * + * Ptgs are logically arranged in a tree representing the structure of the + * parsed formula. However, in BIFF files Ptgs are written/read in + * Reverse-Polish Notation order. The RPN ordering also simplifies formula + * evaluation logic, so POI mostly accesses Ptgs in the same way. * * @author andy * @author avik * @author Jason Height (jheight at chariot dot net dot au) */ -public abstract class Ptg -{ +public abstract class Ptg implements Cloneable { + /* convert infix order ptg list to rpn order ptg list + * @return List ptgs in RPN order + * @param infixPtgs List of ptgs in infix order + */ - /* convert infix order ptg list to rpn order ptg list - * @return List ptgs in RPN order - * @param infixPtgs List of ptgs in infix order - */ + /* DO NOT REMOVE + *we keep this method in case we wish to change the way we parse + *It needs a getPrecedence in OperationsPtg - /* DO NOT REMOVE - *we keep this method in case we wish to change the way we parse - *It needs a getPrecedence in OperationsPtg + public static List ptgsToRpn(List infixPtgs) { + java.util.Stack operands = new java.util.Stack(); + java.util.List retval = new java.util.Stack(); - public static List ptgsToRpn(List infixPtgs) { - java.util.Stack operands = new java.util.Stack(); - java.util.List retval = new java.util.Stack(); + java.util.ListIterator i = infixPtgs.listIterator(); + Object p; + OperationPtg o ; + boolean weHaveABracket = false; + while (i.hasNext()) { + p=i.next(); + if (p instanceof OperationPtg) { + if (p instanceof ParenthesisPtg) { + if (!weHaveABracket) { + operands.push(p); + weHaveABracket = true; + } else { + o = (OperationPtg) operands.pop(); + while (!(o instanceof ParenthesisPtg)) { + retval.add(o); + } + weHaveABracket = false; + } + } else { - java.util.ListIterator i = infixPtgs.listIterator(); - Object p; - OperationPtg o ; - boolean weHaveABracket = false; - while (i.hasNext()) { - p=i.next(); - if (p instanceof OperationPtg) { - if (p instanceof ParenthesisPtg) { - if (!weHaveABracket) { - operands.push(p); - weHaveABracket = true; - } else { - o = (OperationPtg) operands.pop(); - while (!(o instanceof ParenthesisPtg)) { - retval.add(o); - } - weHaveABracket = false; - } - } else { + while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative + retval.add(operands.pop()); + } + operands.push(p); + } + } else { + retval.add(p); + } + } + while (!operands.isEmpty()) { + if (operands.peek() instanceof ParenthesisPtg ){ + //throw some error + } else { + retval.add(operands.pop()); + } + } + return retval; + } + */ + + /** + * Reads size bytes of the input stream, to create an array of Ptgs. + * Extra data (beyond size) may be read if and ArrayPtgs are present. + */ + public static Ptg[] readTokens(int size, RecordInputStream in) { + Stack temp = createParsedExpressionTokens((short)size, in); + return toPtgArray(temp); + } - while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative - retval.add(operands.pop()); - } - operands.push(p); - } - } else { - retval.add(p); - } - } - while (!operands.isEmpty()) { - if (operands.peek() instanceof ParenthesisPtg ){ - //throw some error - } else { - retval.add(operands.pop()); - } - } - return retval; - } - */ + /** + * @deprecated - use readTokens() + */ + public static Stack createParsedExpressionTokens(short size, RecordInputStream in) + { + Stack stack = new Stack(); + int pos = 0; + List arrayPtgs = null; + while ( pos < size ) + { + Ptg ptg = Ptg.createPtg( in ); + if (ptg instanceof ArrayPtg) { + if (arrayPtgs == null) + arrayPtgs = new ArrayList(5); + arrayPtgs.add(ptg); + pos += 8; + } else pos += ptg.getSize(); + stack.push( ptg ); + } + if(pos != size) { + throw new RuntimeException("Ptg array size mismatch"); + } + if (arrayPtgs != null) { + for (int i=0;isize bytes of the input stream, to create an array of Ptgs. - * Extra data (beyond size) may be read if and ArrayPtgs are present. - */ - public static Stack createParsedExpressionTokens(short size, RecordInputStream in ) - { - Stack stack = new Stack(); - int pos = 0; - List arrayPtgs = null; - while ( pos < size ) - { - Ptg ptg = Ptg.createPtg( in ); - if (ptg instanceof ArrayPtg) { - if (arrayPtgs == null) - arrayPtgs = new ArrayList(5); - arrayPtgs.add(ptg); - pos += 8; - } else pos += ptg.getSize(); - stack.push( ptg ); - } - if(pos != size) { - throw new RuntimeException("Ptg array size mismatch"); - } - if (arrayPtgs != null) { - for (int i=0;i 0x60) { + retval.setClass(CLASS_ARRAY); + } else if (id > 0x40) { + retval.setClass(CLASS_VALUE); + } else { + retval.setClass(CLASS_REF); + } - if (id > 0x60) { - retval.setClass(CLASS_ARRAY); - } else if (id > 0x40) { - retval.setClass(CLASS_VALUE); - } else { - retval.setClass(CLASS_REF); - } - - return retval; - - } + return retval; + } private static Ptg createClassifiedPtg(byte id, RecordInputStream in) { int baseId = id & 0x1F | 0x20; - switch (baseId) { - case FuncPtg.sid: return new FuncPtg(in); // 0x21, 0x41, 0x61 - case FuncVarPtg.sid: return new FuncVarPtg(in); // 0x22, 0x42, 0x62 - case NamePtg.sid: return new NamePtg(in); // 0x23, 0x43, 0x63 + switch (baseId) { + case ArrayPtg.sid: return new ArrayPtg(in); // 0x20, 0x40, 0x60 + case FuncPtg.sid: return new FuncPtg(in); // 0x21, 0x41, 0x61 + case FuncVarPtg.sid: return new FuncVarPtg(in); // 0x22, 0x42, 0x62 + case NamePtg.sid: return new NamePtg(in); // 0x23, 0x43, 0x63 + case RefPtg.sid: return new RefPtg(in); // 0x24, 0x44, 0x64 + case AreaPtg.sid: return new AreaPtg(in); // 0x25, 0x45, 0x65 + case MemAreaPtg.sid: return new MemAreaPtg(in); // 0x26, 0x46, 0x66 + case MemErrPtg.sid: return new MemErrPtg(in); // 0x27, 0x47, 0x67 + case MemFuncPtg.sid: return new MemFuncPtg(in); // 0x29, 0x49, 0x69 + case RefErrorPtg.sid: return new RefErrorPtg(in);// 0x2a, 0x4a, 0x6a + case AreaErrPtg.sid: return new AreaErrPtg(in); // 0x2b, 0x4b, 0x6b + case RefNPtg.sid: return new RefNPtg(in); // 0x2c, 0x4c, 0x6c + case AreaNPtg.sid: return new AreaNPtg(in); // 0x2d, 0x4d, 0x6d - case MemAreaPtg.sid: return new MemAreaPtg(in); // 0x26, 0x46, 0x66 - case MemErrPtg.sid: return new MemErrPtg(in); // 0x27, 0x47, 0x67 - case MemFuncPtg.sid: return new MemFuncPtg(in); // 0x29, 0x49, 0x69 - case RefErrorPtg.sid: return new RefErrorPtg(in);// 0x2a, 0x4a, 0x6a - case AreaErrPtg.sid: return new AreaErrPtg(in); // 0x2b, 0x4b, 0x6b - - case NameXPtg.sid: return new NameXPtg(in); // 0x39, 0x49, 0x79 - case Ref3DPtg.sid: return new Ref3DPtg(in); // 0x3a, 0x5a, 0x7a - case Area3DPtg.sid: return new Area3DPtg(in); // 0x3b, 0x5b, 0x7b - case DeletedRef3DPtg.sid: return new DeletedRef3DPtg(in); // 0x3c, 0x5c, 0x7c - case DeletedArea3DPtg.sid: return new DeletedArea3DPtg(in); // 0x3d, 0x5d, 0x7d - } - - - switch (id) { - // TODO - why are specific subclasses needed for these Ptgs? - case ArrayPtg.sid: return new ArrayPtg(in); // 0x20 - case ArrayPtgV.sid: return new ArrayPtgV(in); // 0x40 - case ArrayPtgA.sid: return new ArrayPtgA(in); // 0x60 - - case ReferencePtg.sid: return new ReferencePtg(in);// 0x24 - case RefAPtg.sid: return new RefAPtg(in); // 0x64 - case RefVPtg.sid: return new RefVPtg(in); // 0x44 - - case RefNAPtg.sid: return new RefNAPtg(in); // 0x6C - case RefNPtg.sid: return new RefNPtg(in); // 0x2C - case RefNVPtg.sid: return new RefNVPtg(in); // 0x4C - - case AreaPtg.sid: return new AreaPtg(in); // 0x25 - case AreaVPtg.sid: return new AreaVPtg(in); // 0x45 - case AreaAPtg.sid: return new AreaAPtg(in); // 0x65 - - case AreaNAPtg.sid: return new AreaNAPtg(in); // 0x6D - case AreaNPtg.sid: return new AreaNPtg(in); // 0x2D - case AreaNVPtg.sid: return new AreaNVPtg(in); // 0x4D - - } - throw new UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+ - Integer.toHexString(id) + " (" + ( int ) id + ")"); + case NameXPtg.sid: return new NameXPtg(in); // 0x39, 0x49, 0x79 + case Ref3DPtg.sid: return new Ref3DPtg(in); // 0x3a, 0x5a, 0x7a + case Area3DPtg.sid: return new Area3DPtg(in); // 0x3b, 0x5b, 0x7b + case DeletedRef3DPtg.sid: return new DeletedRef3DPtg(in); // 0x3c, 0x5c, 0x7c + case DeletedArea3DPtg.sid: return new DeletedArea3DPtg(in); // 0x3d, 0x5d, 0x7d + } + throw new UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+ + Integer.toHexString(id) + " (" + ( int ) id + ")"); } private static Ptg createBasePtg(byte id, RecordInputStream in) { switch(id) { - case 0x00: return new UnknownPtg(); // TODO - not a real Ptg - case ExpPtg.sid: return new ExpPtg(in); // 0x01 - case AddPtg.sid: return new AddPtg(in); // 0x03 - case SubtractPtg.sid: return new SubtractPtg(in); // 0x04 - case MultiplyPtg.sid: return new MultiplyPtg(in); // 0x05 - case DividePtg.sid: return new DividePtg(in); // 0x06 - case PowerPtg.sid: return new PowerPtg(in); // 0x07 - case ConcatPtg.sid: return new ConcatPtg(in); // 0x08 - case LessThanPtg.sid: return new LessThanPtg(in); // 0x09 - case LessEqualPtg.sid: return new LessEqualPtg(in); // 0x0a - case EqualPtg.sid: return new EqualPtg(in); // 0x0b - case GreaterEqualPtg.sid: return new GreaterEqualPtg(in);// 0x0c - case GreaterThanPtg.sid: return new GreaterThanPtg(in); // 0x0d - case NotEqualPtg.sid: return new NotEqualPtg(in); // 0x0e - case IntersectionPtg.sid: return new IntersectionPtg(in);// 0x0f - case UnionPtg.sid: return new UnionPtg(in); // 0x10 - case RangePtg.sid: return new RangePtg(in); // 0x11 - case UnaryPlusPtg.sid: return new UnaryPlusPtg(in); // 0x12 - case UnaryMinusPtg.sid: return new UnaryMinusPtg(in); // 0x13 - case PercentPtg.sid: return new PercentPtg(in); // 0x14 - case ParenthesisPtg.sid: return new ParenthesisPtg(in); // 0x15 - case MissingArgPtg.sid: return new MissingArgPtg(in); // 0x16 - case StringPtg.sid: return new StringPtg(in); // 0x17 - case AttrPtg.sid: - case 0x1a: return new AttrPtg(in); // 0x19 - case ErrPtg.sid: return new ErrPtg(in); // 0x1c - case BoolPtg.sid: return new BoolPtg(in); // 0x1d - case IntPtg.sid: return new IntPtg(in); // 0x1e - case NumberPtg.sid: return new NumberPtg(in); // 0x1f + case 0x00: return new UnknownPtg(); // TODO - not a real Ptg + case ExpPtg.sid: return new ExpPtg(in); // 0x01 + case AddPtg.sid: return AddPtg.instance; // 0x03 + case SubtractPtg.sid: return SubtractPtg.instance; // 0x04 + case MultiplyPtg.sid: return MultiplyPtg.instance; // 0x05 + case DividePtg.sid: return DividePtg.instance; // 0x06 + case PowerPtg.sid: return PowerPtg.instance; // 0x07 + case ConcatPtg.sid: return ConcatPtg.instance; // 0x08 + case LessThanPtg.sid: return LessThanPtg.instance; // 0x09 + case LessEqualPtg.sid: return LessEqualPtg.instance; // 0x0a + case EqualPtg.sid: return EqualPtg.instance; // 0x0b + case GreaterEqualPtg.sid: return GreaterEqualPtg.instance;// 0x0c + case GreaterThanPtg.sid: return GreaterThanPtg.instance; // 0x0d + case NotEqualPtg.sid: return NotEqualPtg.instance; // 0x0e + case IntersectionPtg.sid: return IntersectionPtg.instance;// 0x0f + case UnionPtg.sid: return UnionPtg.instance; // 0x10 + case RangePtg.sid: return RangePtg.instance; // 0x11 + case UnaryPlusPtg.sid: return UnaryPlusPtg.instance; // 0x12 + case UnaryMinusPtg.sid: return UnaryMinusPtg.instance; // 0x13 + case PercentPtg.sid: return PercentPtg.instance; // 0x14 + case ParenthesisPtg.sid: return ParenthesisPtg.instance; // 0x15 + case MissingArgPtg.sid: return MissingArgPtg.instance; // 0x16 + + case StringPtg.sid: return new StringPtg(in); // 0x17 + case AttrPtg.sid: + case 0x1a: return new AttrPtg(in); // 0x19 + case ErrPtg.sid: return new ErrPtg(in); // 0x1c + case BoolPtg.sid: return new BoolPtg(in); // 0x1d + case IntPtg.sid: return new IntPtg(in); // 0x1e + case NumberPtg.sid: return new NumberPtg(in); // 0x1f } throw new RuntimeException("Unexpected base token id (" + id + ")"); } - /** - * - * - */ + /** + * + * + */ public static int getEncodedSize(Stack ptgs) { return getEncodedSize(toPtgArray(ptgs)); } + /** + * @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) { Ptg[] result = new Ptg[l.size()]; l.toArray(result); return result; } - private static Stack createStack(Ptg[] formulaTokens) { + private static Stack createStack(Ptg[] formulaTokens) { Stack result = new Stack(); for (int i = 0; i < formulaTokens.length; i++) { result.add(formulaTokens[i]); @@ -251,110 +268,120 @@ public abstract class Ptg } return result; } + /** + * Writes the ptgs to the data buffer, starting at the specified offset. + * + *
+ * The 2 byte encode length field is not written by this method. + * @return number of bytes written + */ + public static int serializePtgs(Ptg[] ptgs, byte[] data, int offset) { + return serializePtgStack(createStack(ptgs), data, offset); + } - public static int serializePtgStack(Stack expression, byte[] array, int offset) { - int pos = 0; - int size = 0; - if (expression != null) - size = expression.size(); + /** + * @deprecated use serializePtgs() + */ + public static int serializePtgStack(Stack expression, byte[] array, int offset) { + int pos = 0; + int size = 0; + if (expression != null) + size = expression.size(); - List arrayPtgs = null; + List arrayPtgs = null; - for (int k = 0; k < size; k++) { - Ptg ptg = ( Ptg ) expression.get(k); + for (int k = 0; k < size; k++) { + Ptg ptg = ( Ptg ) expression.get(k); - ptg.writeBytes(array, pos + offset); - if (ptg instanceof ArrayPtg) { - if (arrayPtgs == null) - arrayPtgs = new ArrayList(5); - arrayPtgs.add(ptg); - pos += 8; - } else pos += ptg.getSize(); - } - if (arrayPtgs != null) { - for (int i=0;ifalse if this token is classified as 'reference', 'value', or 'array' - */ - public abstract boolean isBaseToken(); + /** + * @return false if this token is classified as 'reference', 'value', or 'array' + */ + public abstract boolean isBaseToken(); } diff --git a/src/java/org/apache/poi/hssf/record/formula/RangePtg.java b/src/java/org/apache/poi/hssf/record/formula/RangePtg.java index 05cb6defe..d6076f2ba 100644 --- a/src/java/org/apache/poi/hssf/record/formula/RangePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/RangePtg.java @@ -18,7 +18,6 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** * @author Daniel Noll (daniel at nuix dot com dot au) @@ -27,20 +26,16 @@ public final class RangePtg extends OperationPtg { public final static int SIZE = 1; public final static byte sid = 0x11; - public RangePtg() - { - } + public static final OperationPtg instance = new RangePtg(); - public RangePtg(RecordInputStream in) - { - // No contents + private RangePtg() { + // enforce singleton } public final boolean isBaseToken() { return true; } - public int getSize() { return SIZE; @@ -51,17 +46,6 @@ public final class RangePtg extends OperationPtg { array[ offset + 0 ] = sid; } - public Object clone() - { - return new RangePtg(); - } - - public int getType() - { - return TYPE_BINARY; - } - - /** Implementation of method from Ptg */ public String toFormulaString(Workbook book) { return ":"; 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 fa1563c04..8a4311dba 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java @@ -82,7 +82,7 @@ public class Ref3DPtg extends OperandPtg { } public void writeBytes(byte [] array, int offset) { - array[ 0 + offset ] = (byte) (sid + ptgClass); + array[ 0 + offset ] = (byte) (sid + getPtgClass()); LittleEndian.putShort(array, 1 + offset , getExternSheetIndex()); LittleEndian.putShort(array, 3 + offset , (short)getRow()); LittleEndian.putShort(array, 5 + offset , (short)getColumnRaw()); @@ -190,14 +190,7 @@ public class Ref3DPtg extends OperandPtg { return retval.toString(); } - public byte getDefaultOperandClass() {return Ptg.CLASS_REF;} - - public Object clone() { - Ref3DPtg ptg = new Ref3DPtg(); - ptg.field_1_index_extern_sheet = field_1_index_extern_sheet; - ptg.field_2_row = field_2_row; - ptg.field_3_column = field_3_column; - ptg.setClass(ptgClass); - return ptg; - } + public byte getDefaultOperandClass() { + return Ptg.CLASS_REF; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java index fed32ddad..6adbe43c5 100755 --- a/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java @@ -17,12 +17,9 @@ package org.apache.poi.hssf.record.formula; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.BitField; - -import org.apache.poi.hssf.util.CellReference; -import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.LittleEndian; /** * RefError - handles deleted cell reference @@ -34,10 +31,6 @@ public final class RefErrorPtg extends OperandPtg { public final static byte sid = 0x2a; private int field_1_reserved; - private RefErrorPtg() { - //Required for clone methods - } - public RefErrorPtg(RecordInputStream in) { field_1_reserved = in.readInt(); @@ -54,7 +47,7 @@ public final class RefErrorPtg extends OperandPtg { public void writeBytes(byte [] array, int offset) { - array[offset] = (byte) (sid + ptgClass); + array[offset] = (byte) (sid + getPtgClass()); LittleEndian.putInt(array,offset+1,field_1_reserved); } @@ -82,11 +75,4 @@ public final class RefErrorPtg extends OperandPtg { public byte getDefaultOperandClass() { return Ptg.CLASS_REF; } - - public Object clone() { - RefErrorPtg ptg = new RefErrorPtg(); - ptg.field_1_reserved = field_1_reserved; - ptg.setClass(ptgClass); - return ptg; - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/RefNAPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefNAPtg.java deleted file mode 100644 index 4a9b85bc7..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/RefNAPtg.java +++ /dev/null @@ -1,52 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.ss.usermodel.Workbook; - -/** - * RefNAPtg - * @author Jason Height (jheight at chariot dot net dot au) - */ -public final class RefNAPtg extends ReferencePtg -{ - public final static byte sid = 0x6C; - - protected RefNAPtg() { - //Required for clone methods - } - - public RefNAPtg(RecordInputStream in) - { - super(in); - } - - public String getRefPtgName() { - return "RefNAPtg"; - } - - public String toFormulaString(Workbook book) - { - throw notImplemented(); - } - - public Object clone() { - throw notImplemented(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java index 5c8d93c79..5ef4a413b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java @@ -18,37 +18,21 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.ss.usermodel.Workbook; /** * RefNPtg * @author Jason Height (jheight at apache dot com) */ -public final class RefNPtg extends ReferencePtg -{ +public final class RefNPtg extends RefPtgBase { public final static byte sid = 0x2C; - protected RefNPtg() { - //Required for clone methods - } - /** Creates new ValueReferencePtg */ - public RefNPtg(RecordInputStream in) - { + public RefNPtg(RecordInputStream in) { super(in); } - - public String getRefPtgName() { - return "RefNPtg"; - } - - public String toFormulaString(Workbook book) - { - throw notImplemented(); - } - - public Object clone() { - throw notImplemented(); + + protected byte getSid() { + return sid; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/RefNVPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefNVPtg.java deleted file mode 100644 index cb2f663d2..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/RefNVPtg.java +++ /dev/null @@ -1,54 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; -import org.apache.poi.ss.usermodel.Workbook; - -/** - * RefNVPtg - * @author Jason Height (jheight at chariot dot net dot au) - */ - -public final class RefNVPtg extends ReferencePtg { - public final static byte sid = 0x4C; - - protected RefNVPtg() { - //Required for clone methods - } - - /** Creates new ValueReferencePtg */ - - public RefNVPtg(RecordInputStream in) - { - super(in); - } - - public String getRefPtgName() { - return "RefNVPtg"; - } - - public String toFormulaString(Workbook book) - { - throw notImplemented(); - } - - public Object clone() { - throw notImplemented(); - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/RefAPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefPtg.java similarity index 60% rename from src/java/org/apache/poi/hssf/record/formula/RefAPtg.java rename to src/java/org/apache/poi/hssf/record/formula/RefPtg.java index 596b38623..a324ce70f 100644 --- a/src/java/org/apache/poi/hssf/record/formula/RefAPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefPtg.java @@ -1,55 +1,53 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; - -/** - * RefNAPtg - * @author Jason Height (jheight at chariot dot net dot au) - */ - -public final class RefAPtg extends ReferencePtg { - public final static byte sid = 0x64; - - protected RefAPtg() { - super(); - } - - public RefAPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) { - super(row, column, isRowRelative, isColumnRelative); - } - - public RefAPtg(RecordInputStream in) - { - super(in); - } - - - public String getRefPtgName() { - return "RefAPtg"; - } - - public Object clone() { - RefAPtg ptg = new RefAPtg(); - ptg.setRow(getRow()); - ptg.setColumnRaw(getColumnRaw()); - ptg.setClass(ptgClass); - return ptg; - } -} +/* ==================================================================== + 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.formula; + +import org.apache.poi.hssf.record.RecordInputStream; + +/** + * 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 RefPtgBase { + public final static byte sid = 0x24; + + /** + * Takes in a String representation of a cell reference and fills out the + * numeric fields. + */ + public RefPtg(String cellref) { + super(cellref); + } + + public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) { + setRow(row); + setColumn(column); + setRowRelative(isRowRelative); + setColRelative(isColumnRelative); + } + + public RefPtg(RecordInputStream in) { + super(in); + } + + protected byte getSid() { + return sid; + } + +} diff --git a/src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java similarity index 65% rename from src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java rename to src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java index d06507e50..87207f6a0 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java @@ -21,31 +21,18 @@ import org.apache.poi.util.LittleEndian; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; -import org.apache.poi.hssf.util.CellReference; +import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.hssf.record.RecordInputStream; /** - * ReferencePtg - handles references (such as A1, A2, IA4) + * 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 class ReferencePtg extends OperandPtg { - /** - * TODO - (May-2008) fix subclasses of ReferencePtg 'RefN~' which are used in shared formulas. - * (See bugzilla 44921) - * The 'RefN~' instances do not work properly, and are expected to be converted by - * SharedFormulaRecord.convertSharedFormulas(). - * This conversion currently does not take place for formulas of named ranges, conditional - * format rules and data validation rules. - * Furthermore, conversion is probably not appropriate in those instances. - */ - protected final RuntimeException notImplemented() { - return new RuntimeException("Coding Error: This method should never be called. This ptg should be converted"); - } +public abstract class RefPtgBase extends OperandPtg { private final static int SIZE = 5; - public final static byte sid = 0x24; private final static int MAX_ROW_NUMBER = 65536; /** The row index - zero based unsigned 16 bit value */ @@ -60,15 +47,15 @@ public class ReferencePtg extends OperandPtg { private static final BitField colRelative = BitFieldFactory.getInstance(0x4000); private static final BitField column = BitFieldFactory.getInstance(0x00FF); - protected ReferencePtg() { + protected RefPtgBase() { //Required for clone methods } /** - * Takes in a String represnetation of a cell reference and fills out the + * Takes in a String representation of a cell reference and fills out the * numeric fields. */ - public ReferencePtg(String cellref) { + protected RefPtgBase(String cellref) { CellReference c= new CellReference(cellref); setRow(c.getRow()); setColumn(c.getCol()); @@ -76,26 +63,19 @@ public class ReferencePtg extends OperandPtg { setRowRelative(!c.isRowAbsolute()); } - public ReferencePtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) { + protected RefPtgBase(int row, int column, boolean isRowRelative, boolean isColumnRelative) { setRow(row); setColumn(column); setRowRelative(isRowRelative); setColRelative(isColumnRelative); } - /** Creates new ValueReferencePtg */ - - public ReferencePtg(RecordInputStream in) - { + protected RefPtgBase(RecordInputStream in) { field_1_row = in.readUShort(); field_2_col = in.readUShort(); } - public String getRefPtgName() { - return "ReferencePtg"; - } - - public String toString() { + public final String toString() { CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative()); StringBuffer sb = new StringBuffer(); sb.append(getClass().getName()); @@ -105,16 +85,16 @@ public class ReferencePtg extends OperandPtg { return sb.toString(); } - public void writeBytes(byte [] array, int offset) - { - array[offset] = (byte) (sid + ptgClass); + public final void writeBytes(byte [] array, int offset) { + array[offset] = (byte) (getSid() + getPtgClass()); LittleEndian.putShort(array, offset+1, (short)field_1_row); LittleEndian.putShort(array, offset+3, (short)field_2_col); } + + protected abstract byte getSid(); - public void setRow(int row) - { + public final void setRow(int row) { if(row < 0 || row >= MAX_ROW_NUMBER) { throw new IllegalArgumentException("The row number, when specified as an integer, must be between 0 and " + MAX_ROW_NUMBER); } @@ -125,81 +105,61 @@ public class ReferencePtg extends OperandPtg { * Returns the row number as a short, which will be * wrapped (negative) for values between 32769 and 65535 */ - public int getRow() - { + public final int getRow(){ return field_1_row; } /** * Returns the row number as an int, between 0 and 65535 */ - public int getRowAsInt() - { - if(field_1_row < 0) { - return field_1_row + MAX_ROW_NUMBER; - } + public final int getRowAsInt() { return field_1_row; } - public boolean isRowRelative() - { + public final boolean isRowRelative() { return rowRelative.isSet(field_2_col); } - public void setRowRelative(boolean rel) { + public final void setRowRelative(boolean rel) { field_2_col=rowRelative.setBoolean(field_2_col,rel); } - public boolean isColRelative() - { + public final boolean isColRelative() { return colRelative.isSet(field_2_col); } - public void setColRelative(boolean rel) { + public final void setColRelative(boolean rel) { field_2_col=colRelative.setBoolean(field_2_col,rel); } - public void setColumnRaw(int col) - { + public final void setColumnRawX(int col) { // TODO field_2_col = col; } - public int getColumnRaw() - { + public int getColumnRawX() { // TODO return field_2_col; } - public void setColumn(int col) - { - if(col < 0 || col > 0x100) { + public final void setColumn(int col) { + if(col < 0 || col >= 0x100) { throw new IllegalArgumentException("Specified colIx (" + col + ") is out of range"); } field_2_col = column.setValue(field_2_col, col); } - public int getColumn() { + public final int getColumn() { return column.getValue(field_2_col); } - public int getSize() - { + public final int getSize() { return SIZE; } - public String toFormulaString(Workbook book) - { + public final String toFormulaString(Workbook book) { //TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe! return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString(); } - public byte getDefaultOperandClass() { + public final byte getDefaultOperandClass() { return Ptg.CLASS_REF; } - - public Object clone() { - ReferencePtg ptg = new ReferencePtg(); - ptg.field_1_row = field_1_row; - ptg.field_2_col = field_2_col; - ptg.setClass(ptgClass); - return ptg; - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java b/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java deleted file mode 100644 index 75c634890..000000000 --- a/src/java/org/apache/poi/hssf/record/formula/RefVPtg.java +++ /dev/null @@ -1,57 +0,0 @@ -/* ==================================================================== - 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.formula; - -import org.apache.poi.hssf.record.RecordInputStream; - -/** - * RefVPtg - * @author Jason Height (jheight at chariot dot net dot au) - */ -public final class RefVPtg extends ReferencePtg { - public final static byte sid = 0x44; - - protected RefVPtg() { - super(); - } - - public RefVPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) { - super(row, column, isRowRelative, isColumnRelative); - setClass(CLASS_VALUE); - } - - - /** Creates new ValueReferencePtg */ - - public RefVPtg(RecordInputStream in) - { - super(in); - } - - public String getRefPtgName() { - return "RefVPtg"; - } - - public Object clone() { - RefVPtg ptg = new RefVPtg(); - ptg.setRow(getRow()); - ptg.setColumnRaw(getColumnRaw()); - ptg.setClass(ptgClass); - return ptg; - } -} diff --git a/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java b/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java index 43b8c1392..8b00d327f 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java @@ -27,5 +27,4 @@ abstract class ScalarConstantPtg extends Ptg { public final byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/StringPtg.java b/src/java/org/apache/poi/hssf/record/formula/StringPtg.java index 6cd65005e..88b4d9843 100644 --- a/src/java/org/apache/poi/hssf/record/formula/StringPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/StringPtg.java @@ -42,15 +42,11 @@ public final class StringPtg extends ScalarConstantPtg { * NOTE: OO doc says 16bit length, but BiffViewer says 8 Book says something * totally different, so don't look there! */ - private int field_1_length; - private byte field_2_options; - private String field_3_string; + private final int field_1_length; + private final byte field_2_options; + private final String field_3_string; - private StringPtg() { - // Required for clone methods - } - - /** Create a StringPtg from a byte array read from disk */ + /** Create a StringPtg from a stream */ public StringPtg(RecordInputStream in) { field_1_length = in.readUByte(); field_2_options = in.readByte(); @@ -76,9 +72,7 @@ public final class StringPtg extends ScalarConstantPtg { throw new IllegalArgumentException( "String literals in formulas can't be bigger than 255 characters ASCII"); } - field_2_options = 0; - field_2_options = (byte) fHighByte.setBoolean(field_2_options, StringUtil - .hasMultibyte(value)); + field_2_options = (byte) fHighByte.setBoolean(0, StringUtil.hasMultibyte(value)); field_3_string = value; field_1_length = value.length(); // for the moment, we support only ASCII strings in formulas we create } @@ -124,14 +118,6 @@ public final class StringPtg extends ScalarConstantPtg { return sb.toString(); } - public Object clone() { - StringPtg ptg = new StringPtg(); - ptg.field_1_length = field_1_length; - ptg.field_2_options = field_2_options; - ptg.field_3_string = field_3_string; - return ptg; - } - public String toString() { StringBuffer sb = new StringBuffer(64); sb.append(getClass().getName()).append(" ["); diff --git a/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java b/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java index fc99293fd..46fa4cca6 100644 --- a/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java @@ -17,54 +17,27 @@ package org.apache.poi.hssf.record.formula; -import java.util.List; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * * @author andy * @author Jason Height (jheight at chariot dot net dot au) */ public final class SubtractPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x04; - public SubtractPtg() - { + public static final ValueOperatorPtg instance = new SubtractPtg(); + + private SubtractPtg() { + // enforce singleton + } + + protected byte getSid() { + return sid; } - public SubtractPtg(RecordInputStream in) - { - - // doesn't need anything - } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; - } - - public int getSize() - { - return SIZE; - } - - public int getType() - { - return TYPE_BINARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 2; } - - public String toFormulaString(Workbook book) - { - return "-"; - } - public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); @@ -74,8 +47,4 @@ public final class SubtractPtg extends ValueOperatorPtg { buffer.append(operands[ 1 ]); return buffer.toString(); } - - public Object clone() { - return new SubtractPtg(); - } } diff --git a/src/java/org/apache/poi/hssf/record/formula/UnaryMinusPtg.java b/src/java/org/apache/poi/hssf/record/formula/UnaryMinusPtg.java index 296cf25c5..b8f28ec39 100644 --- a/src/java/org/apache/poi/hssf/record/formula/UnaryMinusPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/UnaryMinusPtg.java @@ -17,62 +17,30 @@ package org.apache.poi.hssf.record.formula; -import java.util.List; - -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * Unary Plus operator * does not have any effect on the operand * @author Avik Sengupta */ - public final class UnaryMinusPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x13; private final static String MINUS = "-"; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new UnaryMinusPtg(); - public UnaryMinusPtg() - { - } - - public UnaryMinusPtg(RecordInputStream in) - { - - // doesn't need anything + private UnaryMinusPtg() { + // enforce singleton } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; + protected byte getSid() { + return sid; } - public int getSize() - { - return SIZE; - } - - public int getType() - { - return this.TYPE_UNARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 1; } - /** Implementation of method from Ptg */ - public String toFormulaString(Workbook book) - { - return "+"; - } - /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); @@ -80,9 +48,4 @@ public final class UnaryMinusPtg extends ValueOperatorPtg { buffer.append(operands[ 0]); return buffer.toString(); } - - public Object clone() { - return new UnaryPlusPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java b/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java index eef161e44..0b050fd53 100644 --- a/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java @@ -17,62 +17,30 @@ package org.apache.poi.hssf.record.formula; -import java.util.List; - -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; - /** * Unary Plus operator * does not have any effect on the operand * @author Avik Sengupta */ - public final class UnaryPlusPtg extends ValueOperatorPtg { - public final static int SIZE = 1; public final static byte sid = 0x12; private final static String ADD = "+"; - /** Creates new AddPtg */ + public static final ValueOperatorPtg instance = new UnaryPlusPtg(); - public UnaryPlusPtg() - { - } - - public UnaryPlusPtg(RecordInputStream in) - { - - // doesn't need anything + private UnaryPlusPtg() { + // enforce singleton } - - public void writeBytes(byte [] array, int offset) - { - array[ offset + 0 ] = sid; + protected byte getSid() { + return sid; } - public int getSize() - { - return SIZE; - } - - public int getType() - { - return this.TYPE_UNARY; - } - - public int getNumberOfOperands() - { + public int getNumberOfOperands() { return 1; } - /** Implementation of method from Ptg */ - public String toFormulaString(Workbook book) - { - return "+"; - } - /** implementation of method from OperationsPtg*/ public String toFormulaString(String[] operands) { StringBuffer buffer = new StringBuffer(); @@ -80,9 +48,4 @@ public final class UnaryPlusPtg extends ValueOperatorPtg { buffer.append(operands[ 0]); return buffer.toString(); } - - public Object clone() { - return new UnaryPlusPtg(); - } - } diff --git a/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java b/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java index 4abc33b86..266f7deca 100644 --- a/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java @@ -18,7 +18,6 @@ package org.apache.poi.hssf.record.formula; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.hssf.record.RecordInputStream; /** * @author Glen Stampoultzis (glens at apache.org) @@ -26,14 +25,10 @@ import org.apache.poi.hssf.record.RecordInputStream; public final class UnionPtg extends OperationPtg { public final static byte sid = 0x10; + public static final OperationPtg instance = new UnionPtg(); - public UnionPtg() - { - } - - public UnionPtg(RecordInputStream in) - { - // doesn't need anything + private UnionPtg() { + // enforce singleton } public final boolean isBaseToken() { @@ -50,17 +45,6 @@ public final class UnionPtg extends OperationPtg { array[ offset + 0 ] = sid; } - public Object clone() - { - return new UnionPtg(); - } - - public int getType() - { - return TYPE_BINARY; - } - - /** Implementation of method from Ptg */ public String toFormulaString(Workbook book) { return ","; diff --git a/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java b/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java index 4ef6ab595..7f5d86cac 100644 --- a/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java +++ b/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf.record.formula; +import org.apache.poi.ss.usermodel.Workbook; + /** * Common superclass of all value operators. * Subclasses include all unary and binary operators except for the reference operators (IntersectionPtg, RangePtg, UnionPtg) @@ -26,12 +28,27 @@ package org.apache.poi.hssf.record.formula; public abstract class ValueOperatorPtg extends OperationPtg { /** - * All Operator Ptgs are base tokens (i.e. are not RVA classifed) + * All Operator Ptgs are base tokens (i.e. are not RVA classified) */ public final boolean isBaseToken() { return true; } + public final byte getDefaultOperandClass() { return Ptg.CLASS_VALUE; } + + public final void writeBytes(byte[] array, int offset) { + array[offset + 0] = getSid(); + } + + protected abstract byte getSid(); + + public final int getSize() { + return 1; + } + public final String toFormulaString(Workbook book) { + // TODO - prune this method out of the hierarchy + throw new RuntimeException("toFormulaString(String[] operands) should be used for subclasses of OperationPtgs"); + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java index 898d7a861..033ecc1f8 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java @@ -17,7 +17,7 @@ package org.apache.poi.hssf.record.formula.eval; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; /** * @author adeshmukh @@ -26,9 +26,9 @@ import org.apache.poi.hssf.record.formula.ReferencePtg; public final class Ref2DEval implements RefEval { private final ValueEval value; - private final ReferencePtg delegate; + private final RefPtg delegate; - public Ref2DEval(ReferencePtg ptg, ValueEval ve) { + public Ref2DEval(RefPtg ptg, ValueEval ve) { if(ve == null) { throw new IllegalArgumentException("ve must not be null"); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 9aa0e966d..7327fc183 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -26,6 +26,7 @@ import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import java.awt.image.BufferedImage; +import java.awt.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Iterator; @@ -46,6 +47,20 @@ public class HSSFPicture public static final int PICTURE_TYPE_PNG = HSSFWorkbook.PICTURE_TYPE_PNG; // PNG public static final int PICTURE_TYPE_DIB = HSSFWorkbook.PICTURE_TYPE_DIB; // Windows DIB + /** + * width of 1px in columns with default width in units of 1/256 of a character width + */ + private static final float PX_DEFAULT = 32.00f; + /** + * width of 1px in columns with overridden width in units of 1/256 of a character width + */ + private static final float PX_MODIFIED = 36.56f; + + /** + * Height of 1px of a row + */ + private static final int PX_ROW = 15; + int pictureIndex; HSSFPatriarch patriarch; @@ -100,59 +115,77 @@ public class HSSFPicture * @since POI 3.0.2 */ public HSSFClientAnchor getPreferredSize(){ - HSSFClientAnchor anchor = new HSSFClientAnchor(); + HSSFClientAnchor anchor = (HSSFClientAnchor)getAnchor(); - EscherBSERecord bse = (EscherBSERecord)patriarch.sheet.book.getBSERecord(pictureIndex); - byte[] data = bse.getBlipRecord().getPicturedata(); - int type = bse.getBlipTypeWin32(); - switch (type){ - //we can calculate the preferred size only for JPEG and PNG - //other formats like WMF, EMF and PICT are not supported in Java - case HSSFWorkbook.PICTURE_TYPE_JPEG: - case HSSFWorkbook.PICTURE_TYPE_PNG: - BufferedImage img = null; - ImageReader r = null; - try { - //read the image using javax.imageio.* - ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) ); - Iterator i = ImageIO.getImageReaders( iis ); - r = (ImageReader) i.next(); - r.setInput( iis ); - img = r.read(0); + Dimension size = getImageDimension(); - int[] dpi = getResolution(r); - int imgWidth = img.getWidth()*96/dpi[0]; - int imgHeight = img.getHeight()*96/dpi[1]; + float w = 0; - //Excel measures cells in units of 1/256th of a character width. - //The cell width calculated based on this info is always "off". - //A better approach seems to be to use empirically obtained cell width and row height - int cellwidth = 64; - int rowheight = 17; + //space in the leftmost cell + w += getColumnWidthInPixels(anchor.col1)*(1 - anchor.dx1/1024); + short col2 = (short)(anchor.col1 + 1); + int dx2 = 0; - int col2 = imgWidth/cellwidth; - int row2 = imgHeight/rowheight; - - int dx2 = (int)((float)(imgWidth % cellwidth)/cellwidth * 1024); - int dy2 = (int)((float)(imgHeight % rowheight)/rowheight * 256); - - anchor.setCol2((short)col2); - anchor.setDx2(dx2); - - anchor.setRow2(row2); - anchor.setDy2(dy2); - - } catch (IOException e){ - //silently return if ImageIO failed to read the image - log.log(POILogger.WARN, e); - img = null; - } - - break; + while(w < size.width){ + w += getColumnWidthInPixels(col2++); } + + if(w > size.width) { + //calculate dx2, offset in the rightmost cell + col2--; + float cw = getColumnWidthInPixels(col2); + float delta = w - size.width; + dx2 = (int)((cw-delta)/cw*1024); + } + anchor.col2 = col2; + anchor.dx2 = dx2; + + float h = 0; + h += (1 - anchor.dy1/256)* getRowHeightInPixels(anchor.row1); + int row2 = anchor.row1 + 1; + int dy2 = 0; + + while(h < size.height){ + h += getRowHeightInPixels(row2++); + } + if(h > size.height) { + row2--; + float ch = getRowHeightInPixels(row2); + float delta = h - size.height; + dy2 = (int)((ch-delta)/ch*256); + } + anchor.row2 = row2; + anchor.dy2 = dy2; + return anchor; } + private float getColumnWidthInPixels(short column){ + + short cw = patriarch.sheet.getColumnWidth(column); + float px = getPixelWidth(column); + + return cw/px; + } + + private float getRowHeightInPixels(int i){ + + HSSFRow row = patriarch.sheet.getRow(i); + float height; + if(row != null) height = row.getHeight(); + else height = patriarch.sheet.getDefaultRowHeight(); + + return height/PX_ROW; + } + + private float getPixelWidth(short column){ + + int def = patriarch.sheet.getDefaultColumnWidth()*256; + short cw = patriarch.sheet.getColumnWidth(column); + + return cw == def ? PX_DEFAULT : PX_MODIFIED; + } + /** * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize @@ -176,4 +209,42 @@ public class HSSFPicture return new int[]{hdpi, vdpi}; } + /** + * Return the dimension of this image + * + * @return image dimension + */ + public Dimension getImageDimension(){ + EscherBSERecord bse = patriarch.sheet.book.getBSERecord(pictureIndex); + byte[] data = bse.getBlipRecord().getPicturedata(); + int type = bse.getBlipTypeWin32(); + Dimension size = new Dimension(); + + switch (type){ + //we can calculate the preferred size only for JPEG and PNG + //other formats like WMF, EMF and PICT are not supported in Java + case HSSFWorkbook.PICTURE_TYPE_JPEG: + case HSSFWorkbook.PICTURE_TYPE_PNG: + case HSSFWorkbook.PICTURE_TYPE_DIB: + try { + //read the image using javax.imageio.* + ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) ); + Iterator i = ImageIO.getImageReaders( iis ); + ImageReader r = (ImageReader) i.next(); + r.setInput( iis ); + BufferedImage img = r.read(0); + + int[] dpi = getResolution(r); + size.width = img.getWidth()*96/dpi[0]; + size.height = img.getHeight()*96/dpi[1]; + + } catch (IOException e){ + //silently return if ImageIO failed to read the image + log.log(POILogger.WARN, e); + } + + break; + } + return size; + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index f33570c10..23ce6120a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -50,7 +50,7 @@ import org.apache.poi.hssf.record.VCenterRecord; import org.apache.poi.hssf.record.WSBoolRecord; import org.apache.poi.hssf.record.WindowTwoRecord; import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.util.HSSFCellRangeAddress; import org.apache.poi.hssf.util.HSSFDataValidation; import org.apache.poi.hssf.util.PaneInformation; @@ -1322,8 +1322,8 @@ public class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet Ptg[] ptgs = fp.getRPNPtg(); boolean changed = false; for(int i=0; i= 0) { @@ -956,8 +954,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm } if (settingRowAndColumn) { - UnionPtg unionPtg = new UnionPtg(); - ptgs.add(unionPtg); + ptgs.add(UnionPtg.instance); } nameRecord.setNameDefinition(ptgs); diff --git a/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java b/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java index 88d8dcecd..4fcc0ffe1 100644 --- a/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java +++ b/src/java/org/apache/poi/ss/usermodel/FormulaEvaluator.java @@ -39,7 +39,7 @@ import org.apache.poi.hssf.record.formula.OperationPtg; import org.apache.poi.hssf.record.formula.ParenthesisPtg; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.record.formula.Ref3DPtg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.StringPtg; import org.apache.poi.hssf.record.formula.UnionPtg; import org.apache.poi.hssf.record.formula.UnknownPtg; @@ -337,17 +337,10 @@ public class FormulaEvaluator { // since we don't know how to handle these yet :( Ptg ptg = ptgs[i]; -<<<<<<< .mine if (ptg instanceof ControlPtg) { // skip Parentheses, Attr, etc continue; } -======= - if (ptg instanceof ControlPtg) { - // skip Parentheses, Attr, etc - continue; - } ->>>>>>> .r663896 if (ptg instanceof MemErrPtg) { continue; } if (ptg instanceof MissingArgPtg) { continue; } if (ptg instanceof NamePtg) { @@ -380,8 +373,8 @@ public class FormulaEvaluator { Eval opresult = invokeOperation(operation, ops, srcRowNum, srcColNum, workbook, sheet); stack.push(opresult); } - else if (ptg instanceof ReferencePtg) { - ReferencePtg refPtg = (ReferencePtg) ptg; + else if (ptg instanceof RefPtg) { + RefPtg refPtg = (RefPtg) ptg; int colIx = refPtg.getColumn(); int rowIx = refPtg.getRow(); Row row = sheet.getRow(rowIx); @@ -526,7 +519,7 @@ public class FormulaEvaluator { /** * returns an appropriate Eval impl instance for the Ptg. The Ptg must be - * one of: Area3DPtg, AreaPtg, ReferencePtg, Ref3DPtg, IntPtg, NumberPtg, + * one of: Area3DPtg, AreaPtg, RefPtg, Ref3DPtg, IntPtg, NumberPtg, * StringPtg, BoolPtg
special Note: OperationPtg subtypes cannot be * passed here! * @@ -545,7 +538,7 @@ public class FormulaEvaluator { Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } - else if (ptg instanceof ReferencePtg) { + else if (ptg instanceof RefPtg) { Constructor constructor = clazz.getConstructor(REFERENCE_CONSTRUCTOR_CLASS_ARRAY); retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg }); } @@ -600,10 +593,10 @@ public class FormulaEvaluator { } /** - * Creates a Ref2DEval for ReferencePtg. + * Creates a Ref2DEval for RefPtg. * Non existent cells are treated as RefEvals containing BlankEval. */ - private static Ref2DEval createRef2DEval(ReferencePtg ptg, Cell cell, + private static Ref2DEval createRef2DEval(RefPtg ptg, Cell cell, Row row, Sheet sheet, Workbook workbook) { if (cell == null) { return new Ref2DEval(ptg, BlankEval.INSTANCE); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java b/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java new file mode 100755 index 000000000..ab6d645d6 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java @@ -0,0 +1,51 @@ +package org.apache.poi.hslf.blip; + +import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.model.Picture; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +/* ==================================================================== + 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. +==================================================================== */ +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; + +/** + * Creates BufferedImage using javax.imageio.ImageIO and draws it in the specified graphics. + * + * @author Yegor Kozlov. + */ +public class BitmapPainter implements ImagePainter { + protected POILogger logger = POILogFactory.getLogger(this.getClass()); + + public void paint(Graphics2D graphics, PictureData pict, Picture parent) { + BufferedImage img; + try { + img = ImageIO.read(new ByteArrayInputStream(pict.getData())); + } + catch (Exception e){ + logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + pict.getType()); + return; + } + Rectangle anchor = parent.getAnchor(); + Image scaledImg = img.getScaledInstance(anchor.width, anchor.height, Image.SCALE_SMOOTH); + graphics.drawImage(scaledImg, anchor.x, anchor.y, null); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java b/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java new file mode 100755 index 000000000..8849a31a2 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java @@ -0,0 +1,71 @@ +/* ==================================================================== + 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.hslf.blip; + +import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.usermodel.PictureData; + +import java.awt.*; + +/** + * A common interface for objects that can render ppt picture data. + *

+ * Subclasses can redefine it and use third-party libraries for actual rendering, + * for example, Bitmaps can be rendered using javax.imageio.* , WMF can be rendered using Apache Batik, + * PICT can be rendered using Apple QuickTime API for Java, etc. + *

+ * + * A typical usage is as follows: + * + * public WMFPaiter implements ImagePainter{ + * public void paint(Graphics2D graphics, PictureData pict, Picture parent){ + * DataInputStream is = new DataInputStream(new ByteArrayInputStream(pict.getData())); + * org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore = + * new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore(); + * try { + * wmfStore.read(is); + * } catch (IOException e){ + * return; + * } + * + * Rectangle anchor = parent.getAnchor(); + * float scale = (float)anchor.width/wmfStore.getWidthPixels(); + * + * org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter = + * new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale); + * graphics.translate(anchor.x, anchor.y); + * painter.paint(graphics); + * } + * } + * PictureData.setImagePainter(Picture.WMF, new WMFPaiter()); + * ... + * + * Subsequent calls of Slide.draw(Graphics gr) will use WMFPaiter for WMF images. + * + * @author Yegor Kozlov. + */ +public interface ImagePainter { + + /** + * Paints the specified picture data + * + * @param graphics the graphics to paintb into + * @param pict the data to paint + * @param parent the shapes that owns the picture data + */ + public void paint(Graphics2D graphics, PictureData pict, Picture parent); +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java index d01136d87..17c1d1c23 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java @@ -51,21 +51,7 @@ public abstract class MasterSheet extends Sheet { if(!(shape instanceof TextShape)) return false; TextShape tx = (TextShape)shape; - TextRun run = tx.getTextRun(); - if(run == null) return false; - - Record[] records = run._records; - for (int i = 0; i < records.length; i++) { - int type = (int)records[i].getRecordType(); - if (type == RecordTypes.BaseTextPropAtom.typeID || - type == RecordTypes.DateTimeMCAtom.typeID || - type == RecordTypes.GenericDateMCAtom.typeID || - type == RecordTypes.FooterMCAtom.typeID || - type == RecordTypes.SlideNumberMCAtom.typeID - ) return true; - - } - return false; + return tx.getPlaceholderAtom() != null; } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java b/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java index 375249b51..34b1fd89b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java @@ -176,16 +176,11 @@ public class Picture extends SimpleShape { public PictureData getPictureData(){ SlideShow ppt = getSheet().getSlideShow(); PictureData[] pict = ppt.getPictureData(); - Document doc = ppt.getDocumentRecord(); - EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); - EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); - List lst = bstore.getChildRecords(); - int idx = getPictureIndex(); - if (idx == 0){ + EscherBSERecord bse = getEscherBSERecord(); + if (bse == null){ logger.log(POILogger.ERROR, "no reference to picture data found "); } else { - EscherBSERecord bse = (EscherBSERecord)lst.get(idx-1); for ( int i = 0; i < pict.length; i++ ) { if (pict[i].getOffset() == bse.getOffset()){ return pict[i]; @@ -196,6 +191,21 @@ public class Picture extends SimpleShape { return null; } + protected EscherBSERecord getEscherBSERecord(){ + SlideShow ppt = getSheet().getSlideShow(); + Document doc = ppt.getDocumentRecord(); + EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); + EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); + + List lst = bstore.getChildRecords(); + int idx = getPictureIndex(); + if (idx == 0){ + return null; + } else { + return (EscherBSERecord)lst.get(idx-1); + } + } + /** * Name of this picture. * @@ -238,6 +248,10 @@ public class Picture extends SimpleShape { */ protected void afterInsert(Sheet sh){ super.afterInsert(sh); + + EscherBSERecord bse = getEscherBSERecord(); + bse.setRef(bse.getRef() + 1); + java.awt.Rectangle anchor = getAnchor(); if (anchor.equals(new java.awt.Rectangle())){ setDefaultSize(); @@ -249,21 +263,8 @@ public class Picture extends SimpleShape { ShapePainter.paint(this, graphics); PictureData data = getPictureData(); - if (data instanceof Bitmap){ - BufferedImage img = null; - try { - img = ImageIO.read(new ByteArrayInputStream(data.getData())); - } - catch (Exception e){ - logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + data.getType()); - return; - } - Rectangle anchor = getAnchor(); - Image scaledImg = img.getScaledInstance(anchor.width, anchor.height, Image.SCALE_SMOOTH); - graphics.drawImage(scaledImg, anchor.x, anchor.y, null); - } else { - logger.log(POILogger.WARN, "Rendering of metafiles is not yet supported. image.type: " + (data == null ? "NA" : data.getClass().getName())); - } + data.draw(graphics, this); + graphics.setTransform(at); } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java index e15454d65..d336cb3f3 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java @@ -20,10 +20,12 @@ package org.apache.poi.hslf.model; import org.apache.poi.ddf.*; import org.apache.poi.util.LittleEndian; import org.apache.poi.hslf.record.ColorSchemeAtom; +import org.apache.poi.hslf.record.Record; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; +import java.util.Iterator; /** * An abstract simple (non-group) shape. @@ -284,4 +286,28 @@ public class SimpleShape extends Shape { ShapePainter.paint(this, graphics); graphics.setTransform(at); } + + /** + * Find a record in the underlying EscherClientDataRecord + * + * @param recordType type of the record to search + */ + protected Record getClientDataRecord(int recordType) { + Record oep = null; + EscherContainerRecord spContainer = getSpContainer(); + for (Iterator it = spContainer.getChildRecords().iterator(); it.hasNext();) { + EscherRecord obj = (EscherRecord) it.next(); + if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) { + byte[] data = obj.serialize(); + Record[] records = Record.findChildRecords(data, 8, data.length - 8); + for (int j = 0; j < records.length; j++) { + if (records[j].getRecordType() == recordType) { + return records[j]; + } + } + } + } + return oep; + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java index bb99c1bca..ee32868eb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java @@ -147,6 +147,7 @@ public class Slide extends Sheet int dgId = dgg.getMaxDrawingGroupId() + 1; dg.setOptions((short)(dgId << 4)); dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1); + dgg.setMaxDrawingGroupId(dgId); for (Iterator it = dgContainer.getChildContainers().iterator(); it.hasNext(); ) { EscherContainerRecord c = (EscherContainerRecord)it.next(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java index 4030ddc0c..27dbe1b2d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java @@ -683,4 +683,13 @@ public class TextRun String ns = s.replaceAll("\\r?\\n", "\r"); return ns; } + + /** + * Returns records that make up this text run + * + * @return text run records + */ + public Record[] getRecords(){ + return _records; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java index 53f8ef97d..d1a84a5e4 100755 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java @@ -1,537 +1,545 @@ - -/* ==================================================================== - 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.hslf.model; - -import org.apache.poi.ddf.*; -import org.apache.poi.hslf.record.*; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.util.POILogger; - -import java.awt.*; -import java.awt.geom.Rectangle2D; -import java.awt.geom.AffineTransform; -import java.awt.font.FontRenderContext; -import java.awt.font.TextLayout; -import java.io.IOException; - -/** - * A common superclass of all shapes that can hold text. - * - * @author Yegor Kozlov - */ -public abstract class TextShape extends SimpleShape { - - /** - * How to anchor the text - */ - public static final int AnchorTop = 0; - public static final int AnchorMiddle = 1; - public static final int AnchorBottom = 2; - public static final int AnchorTopCentered = 3; - public static final int AnchorMiddleCentered = 4; - public static final int AnchorBottomCentered = 5; - public static final int AnchorTopBaseline = 6; - public static final int AnchorBottomBaseline = 7; - public static final int AnchorTopCenteredBaseline = 8; - public static final int AnchorBottomCenteredBaseline = 9; - - /** - * How to wrap the text - */ - public static final int WrapSquare = 0; - public static final int WrapByPoints = 1; - public static final int WrapNone = 2; - public static final int WrapTopBottom = 3; - public static final int WrapThrough = 4; - - /** - * How to align the text - */ - public static final int AlignLeft = 0; - public static final int AlignCenter = 1; - public static final int AlignRight = 2; - public static final int AlignJustify = 3; - - /** - * TextRun object which holds actual text and format data - */ - protected TextRun _txtrun; - - /** - * Escher container which holds text attributes such as - * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc. - */ - protected EscherTextboxWrapper _txtbox; - - /** - * Used to calculate text bounds - */ - protected static final FontRenderContext _frc = new FontRenderContext(null, true, true); - - /** - * Create a TextBox object and initialize it from the supplied Record container. - * - * @param escherRecord EscherSpContainer container which holds information about this shape - * @param parent the parent of the shape - */ - protected TextShape(EscherContainerRecord escherRecord, Shape parent){ - super(escherRecord, parent); - - } - - /** - * Create a new TextBox. This constructor is used when a new shape is created. - * - * @param parent the parent of this Shape. For example, if this text box is a cell - * in a table then the parent is Table. - */ - public TextShape(Shape parent){ - super(null, parent); - _escherContainer = createSpContainer(parent instanceof ShapeGroup); - } - - /** - * Create a new TextBox. This constructor is used when a new shape is created. - * - */ - public TextShape(){ - this(null); - } - - public TextRun createTextRun(){ - _txtbox = getEscherTextboxWrapper(); - if(_txtbox == null) _txtbox = new EscherTextboxWrapper(); - - _txtrun = getTextRun(); - if(_txtrun == null){ - TextHeaderAtom tha = new TextHeaderAtom(); - tha.setParentRecord(_txtbox); - _txtbox.appendChildRecord(tha); - - TextCharsAtom tca = new TextCharsAtom(); - _txtbox.appendChildRecord(tca); - - StyleTextPropAtom sta = new StyleTextPropAtom(0); - _txtbox.appendChildRecord(sta); - - _txtrun = new TextRun(tha,tca,sta); - _txtrun.setText(""); - - _escherContainer.addChildRecord(_txtbox.getEscherRecord()); - - setDefaultTextProperties(_txtrun); - } - - return _txtrun; - } - - /** - * Set default properties for the TextRun. - * Depending on the text and shape type the defaults are different: - * TextBox: align=left, valign=top - * AutoShape: align=center, valign=middle - * - */ - protected void setDefaultTextProperties(TextRun _txtrun){ - - } - - /** - * Returns the text contained in this text frame. - * - * @return the text string for this textbox. - */ - public String getText(){ - TextRun tx = getTextRun(); - return tx == null ? null : tx.getText(); - } - - /** - * Sets the text contained in this text frame. - * - * @param text the text string used by this object. - */ - public void setText(String text){ - TextRun tx = getTextRun(); - if(tx == null){ - tx = createTextRun(); - } - tx.setText(text); - setTextId(text.hashCode()); - } - - /** - * When a textbox is added to a sheet we need to tell upper-level - * PPDrawing about it. - * - * @param sh the sheet we are adding to - */ - protected void afterInsert(Sheet sh){ - super.afterInsert(sh); - - EscherTextboxWrapper _txtbox = getEscherTextboxWrapper(); - if(_txtbox != null){ - PPDrawing ppdrawing = sh.getPPDrawing(); - ppdrawing.addTextboxWrapper(_txtbox); - // Ensure the escher layer knows about the added records - try { - _txtbox.writeOut(null); - } catch (IOException e){ - throw new HSLFException(e); - } - if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText(); - } - } - - protected EscherTextboxWrapper getEscherTextboxWrapper(){ - if(_txtbox == null){ - EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID); - if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord); - } - return _txtbox; - } - /** - * Adjust the size of the TextShape so it encompasses the text inside it. - * - * @return a Rectangle2D that is the bounds of this TextShape. - */ - public Rectangle2D resizeToFitText(){ - String txt = getText(); - if(txt == null || txt.length() == 0) return new Rectangle2D.Float(); - - RichTextRun rt = getTextRun().getRichTextRuns()[0]; - int size = rt.getFontSize(); - int style = 0; - if (rt.isBold()) style |= Font.BOLD; - if (rt.isItalic()) style |= Font.ITALIC; - String fntname = rt.getFontName(); - Font font = new Font(fntname, style, size); - - float width = 0, height = 0; - String[] lines = txt.split("\r"); - for (int i = 0; i < lines.length; i++) { - if(lines[i].length() == 0) continue; - - TextLayout layout = new TextLayout(lines[i], font, _frc); - - width = Math.max(width, layout.getAdvance()); - - /** - * Even if top and bottom margins are set to 0 PowerPoint - * always sets extra space between the text and its bounding box. - * - * The approximation height = ascent*2 works good enough in most cases - */ - height = Math.max(height, 2*layout.getAscent()); - } - - width += getMarginLeft() + getMarginRight(); - height += getMarginTop() + getMarginBottom(); - - Rectangle2D anchor = getAnchor2D(); - anchor.setRect(anchor.getX(), anchor.getY(), width, height); - setAnchor(anchor); - - return anchor; - } - - /** - * Returns the type of vertical alignment for the text. - * One of the Anchor* constants defined in this class. - * - * @return the type of alignment - */ - public int getVerticalAlignment(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT); - int valign = TextShape.AnchorTop; - if (prop == null){ - /** - * If vertical alignment was not found in the shape properties then try to - * fetch the master shape and search for the align property there. - */ - int type = getTextRun().getRunType(); - MasterSheet master = getSheet().getMasterSheet(); - if(master != null){ - TextShape masterShape = master.getPlaceholder(type); - if(masterShape != null) valign = masterShape.getVerticalAlignment(); - } else { - //not found in the master sheet. Use the hardcoded defaults. - switch (type){ - case TextHeaderAtom.TITLE_TYPE: - case TextHeaderAtom.CENTER_TITLE_TYPE: - valign = TextShape.AnchorMiddle; - break; - default: - valign = TextShape.AnchorTop; - break; - } - } - } else { - valign = prop.getPropertyValue(); - } - return valign; - } - - /** - * Sets the type of vertical alignment for the text. - * One of the Anchor* constants defined in this class. - * - * @param align - the type of alignment - */ - public void setVerticalAlignment(int align){ - setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align); - } - - /** - * Sets the type of horizontal alignment for the text. - * One of the Align* constants defined in this class. - * - * @param align - the type of horizontal alignment - */ - public void setHorizontalAlignment(int align){ - TextRun tx = getTextRun(); - if(tx != null) tx.getRichTextRuns()[0].setAlignment(align); - } - - /** - * Gets the type of horizontal alignment for the text. - * One of the Align* constants defined in this class. - * - * @return align - the type of horizontal alignment - */ - public int getHorizontalAlignment(){ - TextRun tx = getTextRun(); - return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment(); - } - - /** - * Returns the distance (in points) between the bottom of the text frame - * and the bottom of the inscribed rectangle of the shape that contains the text. - * Default value is 1/20 inch. - * - * @return the botom margin - */ - public float getMarginBottom(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); - int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the botom margin. - * @see #getMarginBottom() - * - * @param margin the bottom margin - */ - public void setMarginBottom(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT)); - } - - /** - * Returns the distance (in points) between the left edge of the text frame - * and the left edge of the inscribed rectangle of the shape that contains - * the text. - * Default value is 1/10 inch. - * - * @return the left margin - */ - public float getMarginLeft(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); - int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the left margin. - * @see #getMarginLeft() - * - * @param margin the left margin - */ - public void setMarginLeft(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT)); - } - - /** - * Returns the distance (in points) between the right edge of the - * text frame and the right edge of the inscribed rectangle of the shape - * that contains the text. - * Default value is 1/10 inch. - * - * @return the right margin - */ - public float getMarginRight(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT); - int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the right margin. - * @see #getMarginRight() - * - * @param margin the right margin - */ - public void setMarginRight(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT)); - } - - /** - * Returns the distance (in points) between the top of the text frame - * and the top of the inscribed rectangle of the shape that contains the text. - * Default value is 1/20 inch. - * - * @return the top margin - */ - public float getMarginTop(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP); - int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the top margin. - * @see #getMarginTop() - * - * @param margin the top margin - */ - public void setMarginTop(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT)); - } - - - /** - * Returns the value indicating word wrap. - * - * @return the value indicating word wrap. - * Must be one of the Wrap* constants defined in this class. - */ - public int getWordWrap(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT); - return prop == null ? WrapSquare : prop.getPropertyValue(); - } - - /** - * Specifies how the text should be wrapped - * - * @param wrap the value indicating how the text should be wrapped. - * Must be one of the Wrap* constants defined in this class. - */ - public void setWordWrap(int wrap){ - setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap); - } - - /** - * @return id for the text. - */ - public int getTextId(){ - EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); - EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID); - return prop == null ? 0 : prop.getPropertyValue(); - } - - /** - * Sets text ID - * - * @param id of the text - */ - public void setTextId(int id){ - setEscherProperty(EscherProperties.TEXT__TEXTID, id); - } - - /** - * @return the TextRun object for this text box - */ - public TextRun getTextRun(){ - if(_txtrun == null) initTextRun(); - return _txtrun; - } - - public void setSheet(Sheet sheet) { - _sheet = sheet; - - // Initialize _txtrun object. - // (We can't do it in the constructor because the sheet - // is not assigned then, it's only built once we have - // all the records) - TextRun tx = getTextRun(); - if (tx != null) { - // Supply the sheet to our child RichTextRuns - tx.setSheet(_sheet); - RichTextRun[] rt = tx.getRichTextRuns(); - for (int i = 0; i < rt.length; i++) { - rt[i].supplySlideShow(_sheet.getSlideShow()); - } - } - - } - - protected void initTextRun(){ - EscherTextboxWrapper txtbox = getEscherTextboxWrapper(); - Sheet sheet = getSheet(); - - if(sheet == null || txtbox == null) return; - - OutlineTextRefAtom ota = null; - - Record[] child = txtbox.getChildRecords(); - for (int i = 0; i < child.length; i++) { - if (child[i] instanceof OutlineTextRefAtom) { - ota = (OutlineTextRefAtom)child[i]; - break; - } - } - - TextRun[] runs = _sheet.getTextRuns(); - if (ota != null) { - int idx = ota.getTextIndex(); - for (int i = 0; i < runs.length; i++) { - if(runs[i].getIndex() == idx){ - _txtrun = runs[i]; - break; - } - } - if(_txtrun == null) { - logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); - } - } else { - int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId(); - if(runs != null) for (int i = 0; i < runs.length; i++) { - if(runs[i].getShapeId() == shapeId){ - _txtrun = runs[i]; - break; - } - } - } - } - - public void draw(Graphics2D graphics){ - AffineTransform at = graphics.getTransform(); - ShapePainter.paint(this, graphics); - new TextPainter(this).paint(graphics); - graphics.setTransform(at); - } - -} + +/* ==================================================================== + 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.hslf.model; + +import org.apache.poi.ddf.*; +import org.apache.poi.hslf.record.*; +import org.apache.poi.hslf.usermodel.RichTextRun; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.util.POILogger; + +import java.awt.*; +import java.awt.geom.Rectangle2D; +import java.awt.geom.AffineTransform; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.io.IOException; +import java.util.Iterator; + +/** + * A common superclass of all shapes that can hold text. + * + * @author Yegor Kozlov + */ +public abstract class TextShape extends SimpleShape { + + /** + * How to anchor the text + */ + public static final int AnchorTop = 0; + public static final int AnchorMiddle = 1; + public static final int AnchorBottom = 2; + public static final int AnchorTopCentered = 3; + public static final int AnchorMiddleCentered = 4; + public static final int AnchorBottomCentered = 5; + public static final int AnchorTopBaseline = 6; + public static final int AnchorBottomBaseline = 7; + public static final int AnchorTopCenteredBaseline = 8; + public static final int AnchorBottomCenteredBaseline = 9; + + /** + * How to wrap the text + */ + public static final int WrapSquare = 0; + public static final int WrapByPoints = 1; + public static final int WrapNone = 2; + public static final int WrapTopBottom = 3; + public static final int WrapThrough = 4; + + /** + * How to align the text + */ + public static final int AlignLeft = 0; + public static final int AlignCenter = 1; + public static final int AlignRight = 2; + public static final int AlignJustify = 3; + + /** + * TextRun object which holds actual text and format data + */ + protected TextRun _txtrun; + + /** + * Escher container which holds text attributes such as + * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc. + */ + protected EscherTextboxWrapper _txtbox; + + /** + * Used to calculate text bounds + */ + protected static final FontRenderContext _frc = new FontRenderContext(null, true, true); + + /** + * Create a TextBox object and initialize it from the supplied Record container. + * + * @param escherRecord EscherSpContainer container which holds information about this shape + * @param parent the parent of the shape + */ + protected TextShape(EscherContainerRecord escherRecord, Shape parent){ + super(escherRecord, parent); + + } + + /** + * Create a new TextBox. This constructor is used when a new shape is created. + * + * @param parent the parent of this Shape. For example, if this text box is a cell + * in a table then the parent is Table. + */ + public TextShape(Shape parent){ + super(null, parent); + _escherContainer = createSpContainer(parent instanceof ShapeGroup); + } + + /** + * Create a new TextBox. This constructor is used when a new shape is created. + * + */ + public TextShape(){ + this(null); + } + + public TextRun createTextRun(){ + _txtbox = getEscherTextboxWrapper(); + if(_txtbox == null) _txtbox = new EscherTextboxWrapper(); + + _txtrun = getTextRun(); + if(_txtrun == null){ + TextHeaderAtom tha = new TextHeaderAtom(); + tha.setParentRecord(_txtbox); + _txtbox.appendChildRecord(tha); + + TextCharsAtom tca = new TextCharsAtom(); + _txtbox.appendChildRecord(tca); + + StyleTextPropAtom sta = new StyleTextPropAtom(0); + _txtbox.appendChildRecord(sta); + + _txtrun = new TextRun(tha,tca,sta); + _txtrun.setText(""); + + _escherContainer.addChildRecord(_txtbox.getEscherRecord()); + + setDefaultTextProperties(_txtrun); + } + + return _txtrun; + } + + /** + * Set default properties for the TextRun. + * Depending on the text and shape type the defaults are different: + * TextBox: align=left, valign=top + * AutoShape: align=center, valign=middle + * + */ + protected void setDefaultTextProperties(TextRun _txtrun){ + + } + + /** + * Returns the text contained in this text frame. + * + * @return the text string for this textbox. + */ + public String getText(){ + TextRun tx = getTextRun(); + return tx == null ? null : tx.getText(); + } + + /** + * Sets the text contained in this text frame. + * + * @param text the text string used by this object. + */ + public void setText(String text){ + TextRun tx = getTextRun(); + if(tx == null){ + tx = createTextRun(); + } + tx.setText(text); + setTextId(text.hashCode()); + } + + /** + * When a textbox is added to a sheet we need to tell upper-level + * PPDrawing about it. + * + * @param sh the sheet we are adding to + */ + protected void afterInsert(Sheet sh){ + super.afterInsert(sh); + + EscherTextboxWrapper _txtbox = getEscherTextboxWrapper(); + if(_txtbox != null){ + PPDrawing ppdrawing = sh.getPPDrawing(); + ppdrawing.addTextboxWrapper(_txtbox); + // Ensure the escher layer knows about the added records + try { + _txtbox.writeOut(null); + } catch (IOException e){ + throw new HSLFException(e); + } + if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText(); + } + } + + protected EscherTextboxWrapper getEscherTextboxWrapper(){ + if(_txtbox == null){ + EscherTextboxRecord textRecord = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID); + if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord); + } + return _txtbox; + } + /** + * Adjust the size of the TextShape so it encompasses the text inside it. + * + * @return a Rectangle2D that is the bounds of this TextShape. + */ + public Rectangle2D resizeToFitText(){ + String txt = getText(); + if(txt == null || txt.length() == 0) return new Rectangle2D.Float(); + + RichTextRun rt = getTextRun().getRichTextRuns()[0]; + int size = rt.getFontSize(); + int style = 0; + if (rt.isBold()) style |= Font.BOLD; + if (rt.isItalic()) style |= Font.ITALIC; + String fntname = rt.getFontName(); + Font font = new Font(fntname, style, size); + + float width = 0, height = 0, leading = 0; + String[] lines = txt.split("\n"); + for (int i = 0; i < lines.length; i++) { + if(lines[i].length() == 0) continue; + + TextLayout layout = new TextLayout(lines[i], font, _frc); + + leading = Math.max(leading, layout.getLeading()); + width = Math.max(width, layout.getAdvance()); + height = Math.max(height, (height + (layout.getDescent() + layout.getAscent()))); + } + + // add one character to width + Rectangle2D charBounds = font.getMaxCharBounds(_frc); + width += getMarginLeft() + getMarginRight() + charBounds.getWidth(); + + // add leading to height + height += getMarginTop() + getMarginBottom() + leading; + + Rectangle2D anchor = getAnchor2D(); + anchor.setRect(anchor.getX(), anchor.getY(), width, height); + setAnchor(anchor); + + return anchor; + } + + /** + * Returns the type of vertical alignment for the text. + * One of the Anchor* constants defined in this class. + * + * @return the type of alignment + */ + public int getVerticalAlignment(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT); + int valign = TextShape.AnchorTop; + if (prop == null){ + /** + * If vertical alignment was not found in the shape properties then try to + * fetch the master shape and search for the align property there. + */ + int type = getTextRun().getRunType(); + MasterSheet master = getSheet().getMasterSheet(); + if(master != null){ + TextShape masterShape = master.getPlaceholder(type); + if(masterShape != null) valign = masterShape.getVerticalAlignment(); + } else { + //not found in the master sheet. Use the hardcoded defaults. + switch (type){ + case TextHeaderAtom.TITLE_TYPE: + case TextHeaderAtom.CENTER_TITLE_TYPE: + valign = TextShape.AnchorMiddle; + break; + default: + valign = TextShape.AnchorTop; + break; + } + } + } else { + valign = prop.getPropertyValue(); + } + return valign; + } + + /** + * Sets the type of vertical alignment for the text. + * One of the Anchor* constants defined in this class. + * + * @param align - the type of alignment + */ + public void setVerticalAlignment(int align){ + setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align); + } + + /** + * Sets the type of horizontal alignment for the text. + * One of the Align* constants defined in this class. + * + * @param align - the type of horizontal alignment + */ + public void setHorizontalAlignment(int align){ + TextRun tx = getTextRun(); + if(tx != null) tx.getRichTextRuns()[0].setAlignment(align); + } + + /** + * Gets the type of horizontal alignment for the text. + * One of the Align* constants defined in this class. + * + * @return align - the type of horizontal alignment + */ + public int getHorizontalAlignment(){ + TextRun tx = getTextRun(); + return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment(); + } + + /** + * Returns the distance (in points) between the bottom of the text frame + * and the bottom of the inscribed rectangle of the shape that contains the text. + * Default value is 1/20 inch. + * + * @return the botom margin + */ + public float getMarginBottom(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); + int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the botom margin. + * @see #getMarginBottom() + * + * @param margin the bottom margin + */ + public void setMarginBottom(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT)); + } + + /** + * Returns the distance (in points) between the left edge of the text frame + * and the left edge of the inscribed rectangle of the shape that contains + * the text. + * Default value is 1/10 inch. + * + * @return the left margin + */ + public float getMarginLeft(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); + int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the left margin. + * @see #getMarginLeft() + * + * @param margin the left margin + */ + public void setMarginLeft(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT)); + } + + /** + * Returns the distance (in points) between the right edge of the + * text frame and the right edge of the inscribed rectangle of the shape + * that contains the text. + * Default value is 1/10 inch. + * + * @return the right margin + */ + public float getMarginRight(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT); + int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the right margin. + * @see #getMarginRight() + * + * @param margin the right margin + */ + public void setMarginRight(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT)); + } + + /** + * Returns the distance (in points) between the top of the text frame + * and the top of the inscribed rectangle of the shape that contains the text. + * Default value is 1/20 inch. + * + * @return the top margin + */ + public float getMarginTop(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP); + int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the top margin. + * @see #getMarginTop() + * + * @param margin the top margin + */ + public void setMarginTop(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT)); + } + + + /** + * Returns the value indicating word wrap. + * + * @return the value indicating word wrap. + * Must be one of the Wrap* constants defined in this class. + */ + public int getWordWrap(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT); + return prop == null ? WrapSquare : prop.getPropertyValue(); + } + + /** + * Specifies how the text should be wrapped + * + * @param wrap the value indicating how the text should be wrapped. + * Must be one of the Wrap* constants defined in this class. + */ + public void setWordWrap(int wrap){ + setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap); + } + + /** + * @return id for the text. + */ + public int getTextId(){ + EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID); + EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.TEXT__TEXTID); + return prop == null ? 0 : prop.getPropertyValue(); + } + + /** + * Sets text ID + * + * @param id of the text + */ + public void setTextId(int id){ + setEscherProperty(EscherProperties.TEXT__TEXTID, id); + } + + /** + * @return the TextRun object for this text box + */ + public TextRun getTextRun(){ + if(_txtrun == null) initTextRun(); + return _txtrun; + } + + public void setSheet(Sheet sheet) { + _sheet = sheet; + + // Initialize _txtrun object. + // (We can't do it in the constructor because the sheet + // is not assigned then, it's only built once we have + // all the records) + TextRun tx = getTextRun(); + if (tx != null) { + // Supply the sheet to our child RichTextRuns + tx.setSheet(_sheet); + RichTextRun[] rt = tx.getRichTextRuns(); + for (int i = 0; i < rt.length; i++) { + rt[i].supplySlideShow(_sheet.getSlideShow()); + } + } + + } + + protected void initTextRun(){ + EscherTextboxWrapper txtbox = getEscherTextboxWrapper(); + Sheet sheet = getSheet(); + + if(sheet == null || txtbox == null) return; + + OutlineTextRefAtom ota = null; + + Record[] child = txtbox.getChildRecords(); + for (int i = 0; i < child.length; i++) { + if (child[i] instanceof OutlineTextRefAtom) { + ota = (OutlineTextRefAtom)child[i]; + break; + } + } + + TextRun[] runs = _sheet.getTextRuns(); + if (ota != null) { + int idx = ota.getTextIndex(); + for (int i = 0; i < runs.length; i++) { + if(runs[i].getIndex() == idx){ + _txtrun = runs[i]; + break; + } + } + if(_txtrun == null) { + logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); + } + } else { + int shapeId = _escherContainer.getChildById(EscherSpRecord.RECORD_ID).getShapeId(); + if(runs != null) for (int i = 0; i < runs.length; i++) { + if(runs[i].getShapeId() == shapeId){ + _txtrun = runs[i]; + break; + } + } + } + } + + public void draw(Graphics2D graphics){ + AffineTransform at = graphics.getTransform(); + ShapePainter.paint(this, graphics); + new TextPainter(this).paint(graphics); + graphics.setTransform(at); + } + + /** + * Return OEPlaceholderAtom, the atom that describes a placeholder. + * + * @return OEPlaceholderAtom or null if not found + */ + public OEPlaceholderAtom getPlaceholderAtom(){ + return (OEPlaceholderAtom)getClientDataRecord(RecordTypes.OEPlaceholderAtom.typeID); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java index 2f3b898a7..969e9036a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/StyleTextPropAtom.java @@ -138,7 +138,7 @@ public class StyleTextPropAtom extends RecordAtom new TextProp(2, 0x4000, "spaceafter"), new TextProp(2, 0x8000, "para_unknown_4"), new TextProp(2, 0x10000, "para_unknown_5"), - new TextProp(2, 0xE0000, "para_unknown_6"), + new TextProp(2, 0xA0000, "para_unknown_6"), new TextProp(2, 0x200000, "para_unknown_7") }; /** All the different kinds of character properties we might handle */ @@ -167,7 +167,7 @@ public class StyleTextPropAtom extends RecordAtom /** * For the Text Style Properties (StyleTextProp) Atom */ - protected StyleTextPropAtom(byte[] source, int start, int len) { + public StyleTextPropAtom(byte[] source, int start, int len) { // Sanity Checking - we're always at least 8+10 bytes long if(len < 18) { len = 18; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java index 02ff1d9ad..d21d098c3 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java @@ -17,6 +17,8 @@ package org.apache.poi.hslf.usermodel; import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; import org.apache.poi.hslf.model.Picture; import org.apache.poi.hslf.blip.*; import org.apache.poi.hslf.exceptions.HSLFException; @@ -25,6 +27,7 @@ import java.io.OutputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.awt.*; /** * A class that represents image data contained in a slide show. @@ -33,19 +36,21 @@ import java.security.NoSuchAlgorithmException; */ public abstract class PictureData { + protected POILogger logger = POILogFactory.getLogger(this.getClass()); + /** * Size of the image checksum calculated using MD5 algorithm. */ protected static final int CHECKSUM_SIZE = 16; - /** - * Binary data of the picture - */ + /** + * Binary data of the picture + */ private byte[] rawdata; - /** - * The offset to the picture in the stream - */ - protected int offset; + /** + * The offset to the picture in the stream + */ + protected int offset; /** * Returns type of this picture. @@ -71,6 +76,13 @@ public abstract class PictureData { */ protected abstract int getSignature(); + protected static ImagePainter[] painters = new ImagePainter[8]; + static { + PictureData.setImagePainter(Picture.PNG, new BitmapPainter()); + PictureData.setImagePainter(Picture.JPEG, new BitmapPainter()); + PictureData.setImagePainter(Picture.DIB, new BitmapPainter()); + } + /** * Returns the raw binary data of this Picture excluding the first 8 bytes * which hold image signature and size of the image data. @@ -212,4 +224,30 @@ public abstract class PictureData { return getData().length; } + public void draw(Graphics2D graphics, Picture parent){ + ImagePainter painter = painters[getType()]; + if(painter != null) painter.paint(graphics, this, parent); + else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName()); + } + + /** + * Register ImagePainter for the specified image type + * + * @param type image type, must be one of the static constants defined in the Picture class. + * @param painter + */ + public static void setImagePainter(int type, ImagePainter painter){ + painters[type] = painter; + } + + /** + * Return ImagePainter for the specified image type + * + * @param type blip type, must be one of the static constants defined in the Picture class. + * @return ImagePainter for the specified image type + */ + public static ImagePainter getImagePainter(int type){ + return painters[type]; + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java index d969c5b88..56e94431e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java @@ -734,7 +734,7 @@ public class SlideShow else if (format == Picture.WMF) bse.setBlipTypeMacOS((byte)Picture.PICT); else if (format == Picture.PICT) bse.setBlipTypeWin32((byte)Picture.WMF); - bse.setRef(1); + bse.setRef(0); bse.setOffset(offset); bstore.addChildRecord(bse); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java new file mode 100755 index 000000000..d10dd1353 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java @@ -0,0 +1,57 @@ +/* ==================================================================== + 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.hslf.model; + +import junit.framework.*; + +import java.io.FileOutputStream; +import java.io.File; +import java.awt.*; + +import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.blip.ImagePainter; +import org.apache.poi.hslf.blip.BitmapPainter; +import org.apache.poi.ddf.EscherBSERecord; + +/** + * Test Picture shape. + * + * @author Yegor Kozlov + */ +public class TestImagePainter extends TestCase { + + private static class CustomImagePainer implements ImagePainter{ + public void paint(Graphics2D graphics, PictureData pict, Picture parent){ + //do noting + } + + } + + public void testImagePainter() throws Exception { + + ImagePainter pntr = PictureData.getImagePainter(Picture.PNG); + assertTrue(PictureData.getImagePainter(Picture.PNG) instanceof BitmapPainter); + assertTrue(PictureData.getImagePainter(Picture.JPEG) instanceof BitmapPainter); + assertTrue(PictureData.getImagePainter(Picture.DIB) instanceof BitmapPainter); + + PictureData.setImagePainter(Picture.WMF, new CustomImagePainer()); + assertTrue(PictureData.getImagePainter(Picture.WMF) instanceof CustomImagePainer); + } + +} diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java new file mode 100755 index 000000000..cec4f1958 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java @@ -0,0 +1,73 @@ +/* ==================================================================== + 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.hslf.model; + +import junit.framework.*; + +import java.io.FileOutputStream; +import java.io.File; +import java.awt.*; + +import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.ddf.EscherBSERecord; + +/** + * Test Picture shape. + * + * @author Yegor Kozlov + */ +public class TestPicture extends TestCase { + + /** + * Test that the reference count of a blip is incremented every time the picture is inserted. + * This is important when the same image appears multiple times in a slide show. + * + */ + public void testMultiplePictures() throws Exception { + String cwd = System.getProperty("HSLF.testdata.path"); + SlideShow ppt = new SlideShow(); + + Slide s = ppt.createSlide(); + Slide s2 = ppt.createSlide(); + Slide s3 = ppt.createSlide(); + + int idx = ppt.addPicture(new File(cwd, "clock.jpg"), Picture.JPEG); + Picture pict = new Picture(idx); + Picture pict2 = new Picture(idx); + Picture pict3 = new Picture(idx); + + pict.setAnchor(new Rectangle(10,10,100,100)); + s.addShape(pict); + EscherBSERecord bse1 = pict.getEscherBSERecord(); + assertEquals(1, bse1.getRef()); + + pict2.setAnchor(new Rectangle(10,10,100,100)); + s2.addShape(pict2); + EscherBSERecord bse2 = pict.getEscherBSERecord(); + assertSame(bse1, bse2); + assertEquals(2, bse1.getRef()); + + pict3.setAnchor(new Rectangle(10,10,100,100)); + s3.addShape(pict3); + EscherBSERecord bse3 = pict.getEscherBSERecord(); + assertSame(bse2, bse3); + assertEquals(3, bse1.getRef()); + + } + +} diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java index 929279a3c..987ad0b09 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java +++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java @@ -40,7 +40,7 @@ import org.apache.poi.hssf.record.formula.NumberPtg; import org.apache.poi.hssf.record.formula.PercentPtg; import org.apache.poi.hssf.record.formula.PowerPtg; import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.StringPtg; import org.apache.poi.hssf.record.formula.SubtractPtg; import org.apache.poi.hssf.record.formula.UnaryMinusPtg; @@ -165,14 +165,14 @@ public final class TestFormulaParser extends TestCase { public void testUnaryMinus() { Ptg[] ptgs = parseFormula("-A1"); assertEquals(2, ptgs.length); - assertTrue("first ptg is reference",ptgs[0] instanceof ReferencePtg); + assertTrue("first ptg is reference",ptgs[0] instanceof RefPtg); assertTrue("second ptg is Minus",ptgs[1] instanceof UnaryMinusPtg); } public void testUnaryPlus() { Ptg[] ptgs = parseFormula("+A1"); assertEquals(2, ptgs.length); - assertTrue("first ptg is reference",ptgs[0] instanceof ReferencePtg); + assertTrue("first ptg is reference",ptgs[0] instanceof RefPtg); assertTrue("second ptg is Plus",ptgs[1] instanceof UnaryPlusPtg); } @@ -540,11 +540,11 @@ public final class TestFormulaParser extends TestCase { Class[] expClss; expClss = new Class[] { - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // tAttrIf MissingArgPtg.class, AttrPtg.class, // tAttrSkip - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // tAttrSkip FuncVarPtg.class, }; @@ -696,7 +696,7 @@ public final class TestFormulaParser extends TestCase { // FormulaParser strips spaces anyway assertEquals("4", formulaString); - ptgs = new Ptg[] { new IntPtg(3), spacePtg, new IntPtg(4), spacePtg, new AddPtg()}; + ptgs = new Ptg[] { new IntPtg(3), spacePtg, new IntPtg(4), spacePtg, AddPtg.instance, }; formulaString = FormulaParser.toFormulaString(null, ptgs); assertEquals("3+4", formulaString); } @@ -710,7 +710,7 @@ public final class TestFormulaParser extends TestCase { Ptg[] ptgs = { // Excel would probably have put tMissArg here new IntPtg(1), - new DividePtg(), + DividePtg.instance, }; try { FormulaParser.toFormulaString(null, ptgs); diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParserIf.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParserIf.java index ba05c1621..6f7c4747c 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParserIf.java +++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParserIf.java @@ -31,7 +31,7 @@ import org.apache.poi.hssf.record.formula.LessThanPtg; import org.apache.poi.hssf.record.formula.MultiplyPtg; import org.apache.poi.hssf.record.formula.NotEqualPtg; import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.StringPtg; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -61,7 +61,7 @@ public final class TestFormulaParserIf extends TestCase { Class[] expClss; expClss = new Class[] { - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // tAttrIf IntPtg.class, AttrPtg.class, // tAttrSkip @@ -82,9 +82,9 @@ public final class TestFormulaParserIf extends TestCase { Class[] expClss; expClss = new Class[] { - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // tAttrIf - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // tAttrSkip FuncVarPtg.class, }; @@ -100,20 +100,20 @@ public final class TestFormulaParserIf extends TestCase { Class[] expClss; expClss = new Class[] { - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // tAttrIf - ReferencePtg.class, + RefPtg.class, IntPtg.class, MultiplyPtg.class, - ReferencePtg.class, + RefPtg.class, IntPtg.class, AddPtg.class, FuncPtg.class, AttrPtg.class, // tAttrSkip - ReferencePtg.class, - ReferencePtg.class, + RefPtg.class, + RefPtg.class, FuncPtg.class, AttrPtg.class, // tAttrSkip @@ -133,9 +133,9 @@ public final class TestFormulaParserIf extends TestCase { expClss = new Class[] { - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // A tAttrIf - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // B tAttrIf IntPtg.class, AttrPtg.class, // B tAttrSkip @@ -143,7 +143,7 @@ public final class TestFormulaParserIf extends TestCase { AttrPtg.class, // B tAttrSkip FuncVarPtg.class, AttrPtg.class, // A tAttrSkip - ReferencePtg.class, + RefPtg.class, AttrPtg.class, // C tAttrIf IntPtg.class, AttrPtg.class, // C tAttrSkip diff --git a/src/testcases/org/apache/poi/hssf/model/TestRVA.java b/src/testcases/org/apache/poi/hssf/model/TestRVA.java index cb51c17bd..f8c70eb7b 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestRVA.java +++ b/src/testcases/org/apache/poi/hssf/model/TestRVA.java @@ -23,7 +23,7 @@ import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.record.formula.AttrPtg; import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtgBase; import org.apache.poi.hssf.usermodel.FormulaExtractor; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; @@ -102,7 +102,7 @@ public final class TestRVA extends TestCase { for (int i = 0; i < nExcelTokens; i++) { Ptg poiPtg = poiPtgs[i]; Ptg excelPtg = excelPtgs[i]; - if (!areTokenClassesSame(poiPtg, excelPtg)) { + if (excelPtg.getClass() != poiPtg.getClass()) { hasMismatch = true; sb.append(" mismatch token type[" + i + "] " + getShortClassName(excelPtg) + " " + getOperandClassName(excelPtg) + " - " + getShortClassName(poiPtg) + " " @@ -127,17 +127,6 @@ public final class TestRVA extends TestCase { } } - private boolean areTokenClassesSame(Ptg poiPtg, Ptg excelPtg) { - if (excelPtg.getClass() == poiPtg.getClass()) { - return true; - } - if (poiPtg.getClass() == ReferencePtg.class) { - // TODO - remove funny subclasses of ReferencePtg - return excelPtg instanceof ReferencePtg; - } - return false; - } - private String getShortClassName(Object o) { String cn = o.getClass().getName(); int pos = cn.lastIndexOf('.'); diff --git a/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java index 4f5e39087..3fd2b3cf3 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java @@ -26,7 +26,7 @@ import junit.framework.TestCase; import org.apache.poi.hssf.record.formula.AttrPtg; import org.apache.poi.hssf.record.formula.FuncVarPtg; import org.apache.poi.hssf.record.formula.IntPtg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; /** * Tests the serialization and deserialization of the FormulaRecord @@ -130,11 +130,11 @@ public final class TestFormulaRecord extends TestCase { assertEquals(9, ptgs.size()); assertEquals(IntPtg.class, ptgs.get(0).getClass()); assertEquals(AttrPtg.class, ptgs.get(1).getClass()); - assertEquals(ReferencePtg.class, ptgs.get(2).getClass()); + assertEquals(RefPtg.class, ptgs.get(2).getClass()); assertEquals(AttrPtg.class, ptgs.get(3).getClass()); - assertEquals(ReferencePtg.class, ptgs.get(4).getClass()); + assertEquals(RefPtg.class, ptgs.get(4).getClass()); assertEquals(AttrPtg.class, ptgs.get(5).getClass()); - assertEquals(ReferencePtg.class, ptgs.get(6).getClass()); + assertEquals(RefPtg.class, ptgs.get(6).getClass()); assertEquals(AttrPtg.class, ptgs.get(7).getClass()); assertEquals(FuncVarPtg.class, ptgs.get(8).getClass()); diff --git a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java index cb08edec2..92dc95618 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java @@ -25,7 +25,7 @@ import junit.framework.ComparisonFailure; import junit.framework.TestCase; import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.hssf.record.formula.RefAPtg; +import org.apache.poi.hssf.record.formula.RefPtg; /** * @author Josh Micich @@ -68,7 +68,7 @@ public final class TestSharedFormulaRecord extends TestCase { Stack convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 100, 200); - RefAPtg refPtg = (RefAPtg) convertedFormula.get(1); + RefPtg refPtg = (RefPtg) convertedFormula.get(1); assertEquals("$C101", refPtg.toFormulaString(null)); if (refPtg.getPtgClass() == Ptg.CLASS_REF) { throw new AssertionFailedError("Identified bug 45123"); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java index 39464b5e0..2ba27e963 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java @@ -54,12 +54,12 @@ public final class TestArrayPtg extends TestCase { */ public void testReadWriteTokenValueBytes() { - ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA)); + ArrayPtg ptg = new ArrayPtg(new TestcaseRecordInputStream(ArrayPtg.sid, ENCODED_PTG_DATA)); ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA)); assertEquals(3, ptg.getColumnCount()); assertEquals(2, ptg.getRowCount()); - Object[] values = ptg.token_3_arrayValues; + Object[] values = ptg.getTokenArrayValues(); assertEquals(6, values.length); @@ -82,7 +82,7 @@ public final class TestArrayPtg extends TestCase { * Excel stores array elements column by column. This test makes sure POI does the same. */ public void testElementOrdering() { - ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA)); + ArrayPtg ptg = new ArrayPtg(new TestcaseRecordInputStream(ArrayPtg.sid, ENCODED_PTG_DATA)); ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA)); assertEquals(3, ptg.getColumnCount()); assertEquals(2, ptg.getRowCount()); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java index 0bddecd3f..2bc1f42ff 100644 --- a/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java @@ -17,15 +17,19 @@ package org.apache.poi.hssf.record.formula; +import java.util.Arrays; +import java.util.Stack; + import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.TestcaseRecordInputStream; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; /** - * Tests for {@link ReferencePtg}. + * Tests for {@link RefPtg}. */ public final class TestReferencePtg extends TestCase { /** @@ -86,5 +90,18 @@ public final class TestReferencePtg extends TestCase { throw e; } } + private static final byte[] tRefN_data = { + 0x2C, 33, 44, 55, 66, + }; + public void testReadWrite_tRefN_bug45091() { + TestcaseRecordInputStream in = new TestcaseRecordInputStream(-1, tRefN_data); + Stack ptgs = Ptg.createParsedExpressionTokens((short)tRefN_data.length, in); + byte[] outData = new byte[5]; + Ptg.serializePtgStack(ptgs, outData, 0); + if (outData[0] == 0x24) { + throw new AssertionFailedError("Identified bug 45091"); + } + assertTrue(Arrays.equals(tRefN_data, outData)); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java index c1daa094c..699e27fc9 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestPercentEval.java @@ -41,7 +41,7 @@ public final class TestPercentEval extends TestCase { arg, }; - PercentEval opEval = new PercentEval(new PercentPtg()); + PercentEval opEval = new PercentEval(PercentPtg.instance); double result = NumericFunctionInvoker.invoke(opEval, args, -1, (short)-1); assertEquals(expectedResult, result, 0); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java index 724c54cd9..dc20c0d8e 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/eval/TestUnaryPlusEval.java @@ -36,7 +36,7 @@ public final class TestUnaryPlusEval extends TestCase { * The code for handling column operands had been copy-pasted from the row handling code. */ public void testColumnOperand() { - + short firstRow = (short)8; short lastRow = (short)12; short colNum = (short)5; @@ -52,10 +52,9 @@ public final class TestUnaryPlusEval extends TestCase { Eval[] args = { areaEval, }; - - double result = NumericFunctionInvoker.invoke(new UnaryPlusEval(new UnaryPlusPtg()), args, 10, (short)20); - + + double result = NumericFunctionInvoker.invoke(new UnaryPlusEval(UnaryPlusPtg.instance), args, 10, (short)20); + assertEquals(35, result, 0); } - } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java index a6e262b86..9b4a44ea1 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/EvalFactory.java @@ -19,7 +19,7 @@ package org.apache.poi.hssf.record.formula.functions; import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.eval.Area2DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.NumberEval; @@ -58,6 +58,6 @@ final class EvalFactory { * Creates a single RefEval (with value zero) */ public static RefEval createRefEval(String refStr) { - return new Ref2DEval(new ReferencePtg(refStr), ZERO); + return new Ref2DEval(new RefPtg(refStr), ZERO); } } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java index 6d11e5a53..1ec657dfe 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestCountFuncs.java @@ -21,7 +21,7 @@ package org.apache.poi.hssf.record.formula.functions; import junit.framework.TestCase; import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.eval.Area2DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.BlankEval; @@ -124,7 +124,7 @@ public final class TestCountFuncs extends TestCase { }; Area2DEval arg0 = new Area2DEval(new AreaPtg("C1:C6"), values); - Ref2DEval criteriaArg = new Ref2DEval(new ReferencePtg("A1"), new NumberEval(25)); + Ref2DEval criteriaArg = new Ref2DEval(new RefPtg("A1"), new NumberEval(25)); Eval[] args= { arg0, criteriaArg, }; double actual = NumericFunctionInvoker.invoke(new Countif(), args); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java index dc3d595ae..87dd470c6 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestMid.java @@ -18,7 +18,7 @@ package org.apache.poi.hssf.record.formula.functions; import org.apache.poi.hssf.record.formula.AreaPtg; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.eval.Area2DEval; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.BlankEval; @@ -77,7 +77,7 @@ public final class TestMid extends TestCase { // startPos is 1x1 area ref, numChars is cell ref AreaEval aeStart = new Area2DEval(new AreaPtg("A1:A1"), new ValueEval[] { new NumberEval(2), } ); - RefEval reNumChars = new Ref2DEval(new ReferencePtg("B1"), new NumberEval(3)); + RefEval reNumChars = new Ref2DEval(new RefPtg("B1"), new NumberEval(3)); confirmMid(new StringEval("galactic"), aeStart, reNumChars, "ala"); confirmMid(new StringEval("galactic"), new NumberEval(3.1), BlankEval.INSTANCE, ""); diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java index 73043911f..ea06c5e1b 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java @@ -17,7 +17,7 @@ package org.apache.poi.hssf.record.formula.functions; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.Eval; @@ -50,7 +50,7 @@ public final class TestSumproduct extends TestCase { public void testScalarSimple() { - RefEval refEval = new Ref2DEval(new ReferencePtg("A1"), new NumberEval(3)); + RefEval refEval = new Ref2DEval(new RefPtg("A1"), new NumberEval(3)); Eval[] args = { refEval, new NumberEval(2), diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java index 4d63cad1c..c57640eab 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestTFunc.java @@ -17,7 +17,7 @@ package org.apache.poi.hssf.record.formula.functions; -import org.apache.poi.hssf.record.formula.ReferencePtg; +import org.apache.poi.hssf.record.formula.RefPtg; import org.apache.poi.hssf.record.formula.eval.BlankEval; import org.apache.poi.hssf.record.formula.eval.BoolEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval; @@ -50,7 +50,7 @@ public final class TestTFunc extends TestCase { * where cell A1 has the specified innerValue */ private Eval invokeTWithReference(ValueEval innerValue) { - Eval arg = new Ref2DEval(new ReferencePtg((short)1, (short)1, false, false), innerValue); + Eval arg = new Ref2DEval(new RefPtg((short)1, (short)1, false, false), innerValue); return invokeT(arg); }