Changed class hierarchy of Ptg to improve 'operand class' transformation.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@660344 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Josh Micich 2008-05-27 00:57:23 +00:00
parent a8a033be8c
commit 4f1853e01c
48 changed files with 395 additions and 528 deletions

View File

@ -931,6 +931,10 @@ end;
private void setClass(Node n, byte theClass) {
Ptg p = n.getValue();
if (p.isBaseToken()) {
return;
}
if (p instanceof AbstractFunctionPtg || !(p instanceof OperationPtg)) {
p.setClass(theClass);
} else {
@ -988,11 +992,11 @@ end;
// TODO - put comment and throw exception in toFormulaString() of these classes
continue;
}
if (! (ptg instanceof OperationPtg)) {
stack.push(ptg.toFormulaString(book));
if (ptg instanceof ParenthesisPtg) {
String contents = (String)stack.pop();
stack.push ("(" + contents + ")");
continue;
}
if (ptg instanceof AttrPtg) {
AttrPtg attrPtg = ((AttrPtg) ptg);
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
@ -1009,9 +1013,17 @@ end;
// similar to tAttrSpace - RPN is violated
continue;
}
if (!attrPtg.isSum()) {
if (attrPtg.isSum()) {
String[] operands = getOperands(stack, attrPtg.getNumberOfOperands());
stack.push(attrPtg.toFormulaString(operands));
continue;
}
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
}
if (! (ptg instanceof OperationPtg)) {
stack.push(ptg.toFormulaString(book));
continue;
}
OperationPtg o = (OperationPtg) ptg;

View File

@ -44,6 +44,10 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
protected byte field_1_num_args;
protected short field_2_fnc_index;
public final boolean isBaseToken() {
return false;
}
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,11 +15,6 @@
limitations under the License.
==================================================================== */
/*
* AddPtg.java
*
* Created on October 29, 2001, 7:48 PM
*/
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@ -32,10 +26,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Andrew C. Oliver (acoliver@apache.org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class AddPtg
extends OperationPtg
{
public final class AddPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x03;
@ -90,8 +81,6 @@ public class AddPtg
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new AddPtg();
}

View File

@ -35,8 +35,7 @@ import org.apache.poi.util.LittleEndian;
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
public class Area3DPtg extends Ptg implements AreaI
{
public class Area3DPtg extends OperandPtg implements AreaI {
public final static byte sid = 0x3b;
private final static int SIZE = 11; // 10 + 1 for Ptg
private short field_1_index_extern_sheet;

View File

@ -31,7 +31,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class AreaPtg extends Ptg implements AreaI {
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

View File

@ -59,6 +59,10 @@ public class ArrayPtg extends Ptg {
}
}
public boolean isBaseToken() {
return false;
}
/**
* Read in the actual token (array) values. This occurs
* AFTER the last Ptg in the expression.
@ -141,14 +145,15 @@ public class ArrayPtg extends Ptg {
return size;
}
public String toFormulaString(HSSFWorkbook book) {
public String toFormulaString(HSSFWorkbook book)
{
StringBuffer b = new StringBuffer();
b.append("{");
for (int x = 0; x < getColumnCount(); x++) {
for (int x=0;x<getColumnCount();x++) {
if (x > 0) {
b.append(";");
}
for (int y = 0; y < getRowCount(); y++) {
for (int y=0;y<getRowCount();y++) {
if (y > 0) {
b.append(",");
}
@ -169,7 +174,6 @@ public class ArrayPtg extends Ptg {
return "\"" + ((UnicodeString)o).getString() + "\"";
}
if (o instanceof Double) {
// TODO - numeric array elements need default Excel number formatting
return ((Double)o).toString();
}
if (o instanceof Boolean) {

View File

@ -15,7 +15,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@ -32,8 +31,7 @@ import org.apache.poi.util.BitFieldFactory;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public final class AttrPtg extends OperationPtg {
public final class AttrPtg extends ControlPtg {
public final static byte sid = 0x19;
private final static int SIZE = 4;
private byte field_1_options;
@ -290,12 +288,6 @@ public final class AttrPtg extends OperationPtg {
return "UNKNOWN ATTRIBUTE";
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}
public Object clone() {
int[] jt;
if (_jumpTable == null) {

View File

@ -27,10 +27,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class BoolPtg
extends Ptg
{
public final class BoolPtg extends ScalarConstantPtg {
public final static int SIZE = 2;
public final static byte sid = 0x1d;
private boolean field_1_value;
@ -75,8 +72,6 @@ public class BoolPtg
return field_1_value ? "TRUE" : "FALSE";
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
BoolPtg ptg = new BoolPtg();
ptg.field_1_value = field_1_value;

View File

@ -15,7 +15,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@ -26,10 +25,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class ConcatPtg
extends OperationPtg
{
public final class ConcatPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x08;

View File

@ -15,11 +15,25 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
public abstract class ControlPtg
extends Ptg
{
/**
* Common superclass for
* tExp
* tTbl
* tParen
* tNlr
* tAttr
* tSheet
* tEndSheet
*/
public abstract class ControlPtg extends Ptg {
public boolean isBaseToken() {
return true;
}
public final byte getDefaultOperandClass() {
// TODO throw new IllegalStateException("Control tokens are not classified");
return Ptg.CLASS_VALUE;
}
}

View File

@ -15,7 +15,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@ -26,10 +25,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Andrew C. Oliver acoliver at apache dot org
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class DividePtg
extends OperationPtg
{
public final class DividePtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x06;

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -25,10 +24,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
*
* @author andy
*/
public class EqualPtg
extends OperationPtg
{
public final class EqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0b;

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,7 +15,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@ -26,7 +24,7 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
public final class ErrPtg extends Ptg {
public final class ErrPtg extends ScalarConstantPtg {
// convenient access to namespace
private static final HSSFErrorConstants EC = null;
@ -78,10 +76,6 @@ public final class ErrPtg extends Ptg {
return SIZE;
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}
public Object clone() {
return new ErrPtg(field_1_error_code);
}

View File

@ -31,9 +31,7 @@ import org.apache.poi.util.LittleEndian;
* @author dmui (save existing implementation)
*/
public class ExpPtg
extends Ptg
{
public final class ExpPtg extends ControlPtg {
private final static int SIZE = 5;
public final static short sid = 0x1;
private short field_1_first_row;
@ -86,8 +84,6 @@ public class ExpPtg
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
ExpPtg result = new ExpPtg();
result.field_1_first_row = field_1_first_row;

View File

@ -44,6 +44,8 @@ public final class FuncPtg extends AbstractFunctionPtg {
throw new RuntimeException("Invalid built-in function index (" + field_2_fnc_index + ")");
}
numParams = fm.getMinParams();
returnClass = fm.getReturnClassCode();
paramClass = fm.getParameterClassCodes();
}
public FuncPtg(int functionIndex) {
field_2_fnc_index = (short) functionIndex;

View File

@ -40,6 +40,15 @@ public final class FuncVarPtg extends AbstractFunctionPtg{
public FuncVarPtg(RecordInputStream in) {
field_1_num_args = in.readByte();
field_2_fnc_index = in.readShort();
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(field_2_fnc_index);
if(fm == null) {
// Happens only as a result of a call to FormulaParser.parse(), with a non-built-in function name
returnClass = Ptg.CLASS_VALUE;
paramClass = new byte[] {Ptg.CLASS_VALUE};
} else {
returnClass = fm.getReturnClassCode();
paramClass = fm.getParameterClassCodes();
}
}
/**

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,22 +15,17 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
/**
* PTG class to implement greater or equal to
*
* @author fred at stsci dot edu
*/
public class GreaterEqualPtg
extends OperationPtg
{
public final class GreaterEqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0c;

View File

@ -15,26 +15,16 @@
limitations under the License.
==================================================================== */
/*
* GreaterThanPtg.java
*
* Created on January 23, 2003, 9:47 AM
*/
package org.apache.poi.hssf.record.formula;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Greater than operator PTG ">"
* @author Cameron Riley (criley at ekmail.com)
*/
public class GreaterThanPtg
extends OperationPtg
{
public final class GreaterThanPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0D;
private final static String GREATERTHAN = ">";
@ -117,15 +107,6 @@ public class GreaterThanPtg
return buffer.toString();
}
/**
* Get the default operands class value
* @return byte the Ptg Class Value as a byte from the Ptg Parent object
*/
public byte getDefaultOperandClass()
{
return Ptg.CLASS_VALUE;
}
/**
* Implementation of clone method from Object
* @return Object a clone of this class as an Object

View File

@ -27,7 +27,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
public final class IntPtg extends Ptg {
public final class IntPtg extends ScalarConstantPtg {
// 16 bit unsigned integer
private static final int MIN_VALUE = 0x0000;
private static final int MAX_VALUE = 0xFFFF;
@ -75,9 +75,6 @@ public final class IntPtg extends Ptg {
public String toFormulaString(HSSFWorkbook book) {
return String.valueOf(getValue());
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}
public Object clone() {
return new IntPtg(field_1_value);

View File

@ -23,8 +23,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
public class IntersectionPtg extends OperationPtg
{
public final class IntersectionPtg extends OperationPtg {
public final static byte sid = 0x0f;
@ -37,6 +36,9 @@ public class IntersectionPtg extends OperationPtg
// doesn't need anything
}
public final boolean isBaseToken() {
return true;
}
public int getSize()
{

View File

@ -16,7 +16,6 @@
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record.formula;
@ -29,9 +28,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
*
* @author fred at stsci dot edu
*/
public class LessEqualPtg
extends OperationPtg
{
public final class LessEqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0a;

View File

@ -15,18 +15,8 @@
limitations under the License.
==================================================================== */
/*
* LessThanPtg.java
*
* Created on January 23, 2003, 9:47 AM
*/
package org.apache.poi.hssf.record.formula;
//JDK
import java.util.List;
//POI
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
@ -36,9 +26,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* Table 3.5.7
* @author Cameron Riley (criley at ekmail.com)
*/
public class LessThanPtg
extends OperationPtg
{
public final class LessThanPtg extends ValueOperatorPtg {
/** the size of the Ptg */
public final static int SIZE = 1;
@ -125,15 +113,6 @@ public class LessThanPtg
return buffer.toString();
}
/**
* Get the default operands class value
* @return byte the Ptg Class Value as a byte from the Ptg Parent object
*/
public byte getDefaultOperandClass()
{
return Ptg.CLASS_VALUE;
}
/**
* Implementation of clone method from Object
* @return Object a clone of this class as an Object

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,12 +15,6 @@
limitations under the License.
==================================================================== */
/*
* MemAreaPtg.java
*
* Created on November 21, 2001, 8:46 AM
*/
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
@ -31,9 +24,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
public class MemAreaPtg
extends Ptg
{
public class MemAreaPtg extends OperandPtg {
public final static short sid = 0x26;
private final static int SIZE = 7;
private int field_1_reserved;

View File

@ -30,8 +30,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
/**
* @author Glen Stampoultzis (glens at apache.org)
*/
public class MemFuncPtg extends ControlPtg
{
public class MemFuncPtg extends OperandPtg {
public final static byte sid = 0x29;
private short field_1_len_ref_subexpression = 0;

View File

@ -26,9 +26,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* Avik Sengupta &lt;avik at apache.org&gt;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class MissingArgPtg
extends Ptg
{
public final class MissingArgPtg extends ScalarConstantPtg {
private final static int SIZE = 1;
public final static byte sid = 0x16;
@ -60,8 +58,6 @@ public class MissingArgPtg
return " ";
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new MissingArgPtg();
}

View File

@ -25,9 +25,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class MultiplyPtg
extends OperationPtg
{
public final class MultiplyPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x05;

View File

@ -28,10 +28,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class NamePtg
extends Ptg
{
public final class NamePtg extends OperandPtg {
public final static short sid = 0x23;
private final static int SIZE = 5;
/** one-based index to defined name record */

View File

@ -25,7 +25,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
*
* @author aviks
*/
public final class NameXPtg extends Ptg {
public final class NameXPtg extends OperandPtg {
public final static short sid = 0x39;
private final static int SIZE = 7;
private short field_1_ixals; // index to REF entry in externsheet record

View File

@ -26,9 +26,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
*
* @author fred at stsci dot edu
*/
public class NotEqualPtg
extends OperationPtg
{
public final class NotEqualPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x0e;

View File

@ -28,10 +28,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Avik Sengupta
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class NumberPtg
extends Ptg
{
public final class NumberPtg extends ScalarConstantPtg {
public final static int SIZE = 9;
public final static byte sid = 0x1f;
private double field_1_value;
@ -82,7 +79,6 @@ public class NumberPtg
{
return "" + getValue();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
NumberPtg ptg = new NumberPtg();

View File

@ -0,0 +1,31 @@
/* ====================================================================
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;
/**
* @author Josh Micich
*/
public abstract class OperandPtg extends Ptg {
/**
* All Operand <tt>Ptg</tt>s are classifed ('relative', 'value', 'array')
*/
public final boolean isBaseToken() {
return false;
}
}

View File

@ -32,9 +32,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class ParenthesisPtg
extends OperationPtg
{
public final class ParenthesisPtg extends ControlPtg {
private final static int SIZE = 1;
public final static byte sid = 0x15;
@ -61,16 +59,6 @@ public class ParenthesisPtg
return SIZE;
}
public int getType()
{
return TYPE_BINARY;
}
public int getNumberOfOperands()
{
return 1;
}
public String toFormulaString(HSSFWorkbook book)
{
return "()";
@ -81,8 +69,6 @@ public class ParenthesisPtg
return "("+operands[0]+")";
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new ParenthesisPtg();
}

View File

@ -32,9 +32,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Daniel Noll (daniel at nuix.com.au)
*/
public class PercentPtg
extends OperationPtg
{
public final class PercentPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x14;
@ -88,8 +86,6 @@ public class PercentPtg
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new PercentPtg();
}

View File

@ -17,8 +17,6 @@
package org.apache.poi.hssf.record.formula;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.record.RecordInputStream;
@ -27,10 +25,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class PowerPtg
extends OperationPtg
{
public final class PowerPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x07;

View File

@ -119,255 +119,15 @@ public abstract class Ptg
return stack;
}
public static Ptg createPtg(RecordInputStream in)
{
public static Ptg createPtg(RecordInputStream in) {
byte id = in.readByte();
Ptg retval = null;
switch (id)
{
case ExpPtg.sid : // 0x01
retval = new ExpPtg(in);
break;
case AddPtg.sid : // 0x03
retval = new AddPtg(in);
break;
case SubtractPtg.sid : // 0x04
retval = new SubtractPtg(in);
break;
case MultiplyPtg.sid : // 0x05
retval = new MultiplyPtg(in);
break;
case DividePtg.sid : // 0x06
retval = new DividePtg(in);
break;
case PowerPtg.sid : // 0x07
retval = new PowerPtg(in);
break;
case ConcatPtg.sid : // 0x08
retval = new ConcatPtg(in);
break;
case LessThanPtg.sid: // 0x09
retval = new LessThanPtg(in);
break;
case LessEqualPtg.sid : // 0x0a
retval = new LessEqualPtg(in);
break;
case EqualPtg.sid : // 0x0b
retval = new EqualPtg(in);
break;
case GreaterEqualPtg.sid : // 0x0c
retval = new GreaterEqualPtg(in);
break;
case GreaterThanPtg.sid : // 0x0d
retval = new GreaterThanPtg(in);
break;
case NotEqualPtg.sid : // 0x0e
retval = new NotEqualPtg(in);
break;
case IntersectionPtg.sid : // 0x0f
retval = new IntersectionPtg(in);
break;
case UnionPtg.sid : // 0x10
retval = new UnionPtg(in);
break;
case RangePtg.sid : // 0x11
retval = new RangePtg(in);
break;
case UnaryPlusPtg.sid : // 0x12
retval = new UnaryPlusPtg(in);
break;
case UnaryMinusPtg.sid : // 0x13
retval = new UnaryMinusPtg(in);
break;
case PercentPtg.sid : // 0x14
retval = new PercentPtg(in);
break;
case ParenthesisPtg.sid : // 0x15
retval = new ParenthesisPtg(in);
break;
case MissingArgPtg.sid : // 0x16
retval = new MissingArgPtg(in);
break;
case StringPtg.sid : // 0x17
retval = new StringPtg(in);
break;
case AttrPtg.sid : // 0x19
case 0x1a :
retval = new AttrPtg(in);
break;
case ErrPtg.sid : // 0x1c
retval = new ErrPtg(in);
break;
case BoolPtg.sid : // 0x1d
retval = new BoolPtg(in);
break;
case IntPtg.sid : // 0x1e
retval = new IntPtg(in);
break;
case NumberPtg.sid : // 0x1f
retval = new NumberPtg(in);
break;
case ArrayPtg.sid : // 0x20
retval = new ArrayPtg(in);
break;
case ArrayPtgV.sid : // 0x40
retval = new ArrayPtgV(in);
break;
case ArrayPtgA.sid : // 0x60
retval = new ArrayPtgA(in);
break;
case FuncPtg.sid : // 0x21
case FuncPtg.sid + 0x20 : // 0x41
case FuncPtg.sid + 0x40 : // 0x61
retval = new FuncPtg(in);
break;
case FuncVarPtg.sid : // 0x22
case FuncVarPtg.sid + 0x20 : // 0x42
case FuncVarPtg.sid + 0x40 : // 0x62
retval = new FuncVarPtg(in);
break;
case ReferencePtg.sid : // 0x24
retval = new ReferencePtg(in);
break;
case RefAPtg.sid : // 0x64
retval = new RefAPtg(in);
break;
case RefVPtg.sid : // 0x44
retval = new RefVPtg(in);
break;
case RefNAPtg.sid : // 0x6C
retval = new RefNAPtg(in);
break;
case RefNPtg.sid : // 0x2C
retval = new RefNPtg(in);
break;
case RefNVPtg.sid : // 0x4C
retval = new RefNVPtg(in);
break;
case AreaPtg.sid : // 0x25
retval = new AreaPtg(in);
break;
case AreaVPtg.sid: // 0x45
retval = new AreaVPtg(in);
break;
case AreaAPtg.sid: // 0x65
retval = new AreaAPtg(in);
break;
case AreaNAPtg.sid : // 0x6D
retval = new AreaNAPtg(in);
break;
case AreaNPtg.sid : // 0x2D
retval = new AreaNPtg(in);
break;
case AreaNVPtg.sid : // 0x4D
retval = new AreaNVPtg(in);
break;
case MemAreaPtg.sid : // 0x26
case MemAreaPtg.sid + 0x40 : // 0x46
case MemAreaPtg.sid + 0x20 : // 0x66
retval = new MemAreaPtg(in);
break;
case MemErrPtg.sid : // 0x27
case MemErrPtg.sid + 0x20 : // 0x47
case MemErrPtg.sid + 0x40 : // 0x67
retval = new MemErrPtg(in);
break;
case MemFuncPtg.sid : // 0x29
retval = new MemFuncPtg(in);
break;
case RefErrorPtg.sid : // 0x2a
case RefErrorPtg.sid + 0x20 : // 0x4a
case RefErrorPtg.sid + 0x40 : // 0x6a
retval = new RefErrorPtg(in);
break;
case AreaErrPtg.sid : // 0x2b
case AreaErrPtg.sid + 0x20 : // 0x4b
case AreaErrPtg.sid + 0x40 : // 0x6b
retval = new AreaErrPtg(in);
break;
case NamePtg.sid : // 0x23
case NamePtg.sid + 0x20 : // 0x43
case NamePtg.sid + 0x40 : // 0x63
retval = new NamePtg(in);
break;
case NameXPtg.sid : // 0x39
case NameXPtg.sid + 0x20 : // 0x45
case NameXPtg.sid + 0x40 : // 0x79
retval = new NameXPtg(in);
break;
case Area3DPtg.sid : // 0x3b
case Area3DPtg.sid + 0x20 : // 0x5b
case Area3DPtg.sid + 0x40 : // 0x7b
retval = new Area3DPtg(in);
break;
case Ref3DPtg.sid : // 0x3a
case Ref3DPtg.sid + 0x20: // 0x5a
case Ref3DPtg.sid + 0x40: // 0x7a
retval = new Ref3DPtg(in);
break;
case DeletedRef3DPtg.sid: // 0x3c
case DeletedRef3DPtg.sid + 0x20: // 0x5c
case DeletedRef3DPtg.sid + 0x40: // 0x7c
retval = new DeletedRef3DPtg(in);
break;
case DeletedArea3DPtg.sid : // 0x3d
case DeletedArea3DPtg.sid + 0x20 : // 0x5d
case DeletedArea3DPtg.sid + 0x40 : // 0x7d
retval = new DeletedArea3DPtg(in);
break;
case 0x00:
retval = new UnknownPtg();
break;
default :
//retval = new UnknownPtg();
throw new java.lang.UnsupportedOperationException(" Unknown Ptg in Formula: 0x"+
Integer.toHexString(( int ) id) + " (" + ( int ) id + ")");
if (id < 0x20) {
return createBasePtg(id, in);
}
Ptg retval = createClassifiedPtg(id, in);
if (id > 0x60) {
retval.setClass(CLASS_ARRAY);
} else if (id > 0x40) {
@ -380,6 +140,118 @@ public abstract class Ptg
}
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
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 + ")");
}
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
}
throw new RuntimeException("Unexpected base token id (" + id + ")");
}
/**
*
*
*/
public static int getEncodedSize(Stack ptgs) {
return getEncodedSize(toPtgArray(ptgs));
}
private static Ptg[] toPtgArray(List l) {
Ptg[] result = new Ptg[l.size()];
l.toArray(result);
return result;
}
private static Stack createStack(Ptg[] formulaTokens) {
Stack result = new Stack();
for (int i = 0; i < formulaTokens.length; i++) {
result.add(formulaTokens[i]);
}
return result;
}
// TODO - several duplicates of this code should be refactored here
public static int getEncodedSize(Ptg[] ptgs) {
int result = 0;
for (int i = 0; i < ptgs.length; i++) {
result += ptgs[i].getSize();
}
return result;
}
public static int serializePtgStack(Stack expression, byte[] array, int offset) {
int pos = 0;
int size = 0;
@ -408,8 +280,16 @@ public abstract class Ptg
return pos;
}
/**
* @return the encoded length of this Ptg, including the initial Ptg type identifier byte.
*/
public abstract int getSize();
/**
* @return the encoded length of this Ptg, not including the initial Ptg type identifier byte.
*/
// public abstract int getDataSize();
public final byte [] getBytes()
{
int size = getSize();
@ -455,6 +335,9 @@ public abstract class Ptg
protected byte ptgClass = CLASS_REF; //base ptg
public void setClass(byte thePtgClass) {
if (isBaseToken()) {
throw new RuntimeException("setClass should not be called on a base token");
}
ptgClass = thePtgClass;
}
@ -468,5 +351,8 @@ public abstract class Ptg
public abstract Object clone();
/**
* @return <code>false</code> if this token is classified as 'reference', 'value', or 'array'
*/
public abstract boolean isBaseToken();
}

View File

@ -23,8 +23,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
/**
* @author Daniel Noll (daniel at nuix dot com dot au)
*/
public class RangePtg extends OperationPtg
{
public final class RangePtg extends OperationPtg {
public final static int SIZE = 1;
public final static byte sid = 0x11;
@ -37,6 +36,10 @@ public class RangePtg extends OperationPtg
// No contents
}
public final boolean isBaseToken() {
return true;
}
public int getSize()
{

View File

@ -35,8 +35,7 @@ import org.apache.poi.util.LittleEndian;
* @author Jason Height (jheight at chariot dot net dot au)
* @version 1.0-pre
*/
public class Ref3DPtg extends Ptg {
public class Ref3DPtg extends OperandPtg {
public final static byte sid = 0x3a;
private final static int SIZE = 7; // 6 + 1 for Ptg
private short field_1_index_extern_sheet;

View File

@ -28,9 +28,8 @@ import org.apache.poi.hssf.record.RecordInputStream;
* RefError - handles deleted cell reference
* @author Jason Height (jheight at chariot dot net dot au)
*/
public final class RefErrorPtg extends OperandPtg {
public class RefErrorPtg extends Ptg
{
private final static int SIZE = 5;
public final static byte sid = 0x2a;
private int field_1_reserved;

View File

@ -30,7 +30,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Andrew C. Oliver (acoliver@apache.org)
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class ReferencePtg extends Ptg {
public class ReferencePtg extends OperandPtg {
/**
* TODO - (May-2008) fix subclasses of ReferencePtg 'RefN~' which are used in shared formulas.
* (See bugzilla 44921)
@ -95,17 +95,14 @@ public class ReferencePtg extends Ptg {
return "ReferencePtg";
}
public String toString()
{
StringBuffer buffer = new StringBuffer("[");
buffer.append(getRefPtgName());
buffer.append("]\n");
buffer.append("row = ").append(getRow()).append("\n");
buffer.append("col = ").append(getColumn()).append("\n");
buffer.append("rowrelative = ").append(isRowRelative()).append("\n");
buffer.append("colrelative = ").append(isColRelative()).append("\n");
return buffer.toString();
public String toString() {
CellReference cr = new CellReference(getRow(), getColumn(), !isRowRelative(),!isColRelative());
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append(" [");
sb.append(cr.formatAsString());
sb.append("]");
return sb.toString();
}
public void writeBytes(byte [] array, int offset)

View File

@ -0,0 +1,31 @@
/* ====================================================================
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;
/**
* @author Josh Micich
*/
abstract class ScalarConstantPtg extends Ptg {
public boolean isBaseToken() {
return true;
}
public final byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}
}

View File

@ -31,7 +31,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Jason Height (jheight at chariot dot net dot au)
* @author Bernard Chesnoy
*/
public final class StringPtg extends Ptg {
public final class StringPtg extends ScalarConstantPtg {
public final static int SIZE = 9;
public final static byte sid = 0x17;
private static final BitField fHighByte = BitFieldFactory.getInstance(0x01);
@ -124,10 +124,6 @@ public final class StringPtg extends Ptg {
return sb.toString();
}
public byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}
public Object clone() {
StringPtg ptg = new StringPtg();
ptg.field_1_length = field_1_length;

View File

@ -26,10 +26,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class SubtractPtg
extends OperationPtg
{
public final class SubtractPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x04;

View File

@ -28,8 +28,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Avik Sengupta
*/
public class UnaryMinusPtg extends OperationPtg
{
public final class UnaryMinusPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x13;
@ -82,8 +81,6 @@ public class UnaryMinusPtg extends OperationPtg
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new UnaryPlusPtg();
}

View File

@ -28,8 +28,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Avik Sengupta
*/
public class UnaryPlusPtg extends OperationPtg
{
public final class UnaryPlusPtg extends ValueOperatorPtg {
public final static int SIZE = 1;
public final static byte sid = 0x12;
@ -82,8 +81,6 @@ public class UnaryPlusPtg extends OperationPtg
return buffer.toString();
}
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
public Object clone() {
return new UnaryPlusPtg();
}

View File

@ -23,8 +23,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
/**
* @author Glen Stampoultzis (glens at apache.org)
*/
public class UnionPtg extends OperationPtg
{
public final class UnionPtg extends OperationPtg {
public final static byte sid = 0x10;
@ -37,6 +36,9 @@ public class UnionPtg extends OperationPtg
// doesn't need anything
}
public final boolean isBaseToken() {
return true;
}
public int getSize()
{

View File

@ -24,10 +24,7 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author andy
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class UnknownPtg
extends Ptg
{
public class UnknownPtg extends Ptg {
private short size = 1;
/** Creates new UnknownPtg */
@ -36,12 +33,13 @@ public class UnknownPtg
{
}
public UnknownPtg(RecordInputStream in)
{
public UnknownPtg(RecordInputStream in) {
// doesn't need anything
}
public boolean isBaseToken() {
return true;
}
public void writeBytes(byte [] array, int offset)
{
}

View File

@ -0,0 +1,37 @@
/* ====================================================================
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;
/**
* Common superclass of all value operators.
* Subclasses include all unary and binary operators except for the reference operators (IntersectionPtg, RangePtg, UnionPtg)
*
* @author Josh Micich
*/
public abstract class ValueOperatorPtg extends OperationPtg {
/**
* All Operator <tt>Ptg</tt>s are base tokens (i.e. are not RVA classifed)
*/
public final boolean isBaseToken() {
return true;
}
public final byte getDefaultOperandClass() {
return Ptg.CLASS_VALUE;
}
}

View File

@ -342,18 +342,18 @@ public class HSSFFormulaEvaluator {
}
private static ValueEval evaluateCell(HSSFWorkbook workbook, HSSFSheet sheet,
int srcRowNum, short srcColNum, String cellFormulaText) {
FormulaParser parser = new FormulaParser(cellFormulaText, workbook);
parser.parse();
Ptg[] ptgs = parser.getRPNPtg();
// -- parsing over --
Ptg[] ptgs = FormulaParser.parse(cellFormulaText, workbook);
Stack stack = new Stack();
for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
// since we don't know how to handle these yet :(
Ptg ptg = ptgs[i];
if (ptg instanceof ControlPtg) { continue; }
if (ptg instanceof ControlPtg) {
// skip Parentheses, Attr, etc
continue;
}
if (ptg instanceof MemErrPtg) { continue; }
if (ptg instanceof MissingArgPtg) { continue; }
if (ptg instanceof NamePtg) {
@ -371,9 +371,6 @@ public class HSSFFormulaEvaluator {
if (ptg instanceof OperationPtg) {
OperationPtg optg = (OperationPtg) ptg;
// parens can be ignored since we have RPN tokens
if (optg instanceof ParenthesisPtg) { continue; }
if (optg instanceof AttrPtg) { continue; }
if (optg instanceof UnionPtg) { continue; }
OperationEval operation = OperationEvaluatorFactory.create(optg);