]> source.dussan.org Git - poi.git/commitdiff
Changed class hierarchy of Ptg to improve 'operand class' transformation.
authorJosh Micich <josh@apache.org>
Tue, 27 May 2008 00:57:23 +0000 (00:57 +0000)
committerJosh Micich <josh@apache.org>
Tue, 27 May 2008 00:57:23 +0000 (00:57 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@660344 13f79535-47bb-0310-9956-ffa450edef68

48 files changed:
src/java/org/apache/poi/hssf/model/FormulaParser.java
src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java
src/java/org/apache/poi/hssf/record/formula/AddPtg.java
src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
src/java/org/apache/poi/hssf/record/formula/AreaPtg.java
src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
src/java/org/apache/poi/hssf/record/formula/BoolPtg.java
src/java/org/apache/poi/hssf/record/formula/ConcatPtg.java
src/java/org/apache/poi/hssf/record/formula/ControlPtg.java
src/java/org/apache/poi/hssf/record/formula/DividePtg.java
src/java/org/apache/poi/hssf/record/formula/EqualPtg.java
src/java/org/apache/poi/hssf/record/formula/ErrPtg.java
src/java/org/apache/poi/hssf/record/formula/ExpPtg.java
src/java/org/apache/poi/hssf/record/formula/FuncPtg.java
src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java
src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java
src/java/org/apache/poi/hssf/record/formula/GreaterThanPtg.java
src/java/org/apache/poi/hssf/record/formula/IntPtg.java
src/java/org/apache/poi/hssf/record/formula/IntersectionPtg.java
src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java
src/java/org/apache/poi/hssf/record/formula/LessThanPtg.java
src/java/org/apache/poi/hssf/record/formula/MemAreaPtg.java
src/java/org/apache/poi/hssf/record/formula/MemFuncPtg.java
src/java/org/apache/poi/hssf/record/formula/MissingArgPtg.java
src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java
src/java/org/apache/poi/hssf/record/formula/NamePtg.java
src/java/org/apache/poi/hssf/record/formula/NameXPtg.java
src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java
src/java/org/apache/poi/hssf/record/formula/NumberPtg.java
src/java/org/apache/poi/hssf/record/formula/OperandPtg.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java
src/java/org/apache/poi/hssf/record/formula/PercentPtg.java
src/java/org/apache/poi/hssf/record/formula/PowerPtg.java
src/java/org/apache/poi/hssf/record/formula/Ptg.java
src/java/org/apache/poi/hssf/record/formula/RangePtg.java
src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
src/java/org/apache/poi/hssf/record/formula/ReferencePtg.java
src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/record/formula/StringPtg.java
src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java
src/java/org/apache/poi/hssf/record/formula/UnaryMinusPtg.java
src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java
src/java/org/apache/poi/hssf/record/formula/UnionPtg.java
src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java
src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java

index 94cf9978a66a69c038014900d844a36a117d3d41..82f54f0acc51240c67c4b5710aca4b33d95a2fc4 100644 (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()) {
-                    throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
+                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;
index 48d7d4cc5b40aa78845c25e040c617fb2148f913..3c1293807c39dabfd7bb0854c5d2aecd7011b122 100644 (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(" [");
index 4f79d76027c5e32fee678d09b259d62db4b54c2c..c6acbaeb80463722f13a900c164e785c06a35ecd 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    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;
     
@@ -89,8 +80,6 @@ public class AddPtg
         buffer.append(operands[ 1 ]);
         return buffer.toString();
     }
-    
-    public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
            
     public Object clone() {
       return new AddPtg();
index f2b801f6900ea4df2fc4397eb59b5530674ed769..4ee0bef153c472eb98b65d6ca36a9cf9a27102df 100644 (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;
index 969ab5f757b67d12ea8e750bae5fa222fdc4ea61..29d5782e08ce52fc5b92d778066ea3bb5442f4f9 100644 (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
index 49c66e07200a564177f5ff9b2103254e1f81b460..99495a5d22f2a2e2c3dd1aeded324ebc2aa8a3c9 100644 (file)
@@ -47,7 +47,7 @@ public class ArrayPtg extends Ptg {
        protected Object[] token_3_arrayValues;
 
        protected ArrayPtg() {
-               //Required for clone methods
+         //Required for clone methods
        }
 
        public ArrayPtg(RecordInputStream in)
@@ -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.
@@ -89,7 +93,7 @@ public class ArrayPtg extends Ptg {
                for (int x=0;x<getColumnCount();x++) {
                        for (int y=0;y<getRowCount();y++) {
                                Object o = token_3_arrayValues[getValueIndex(x, y)];
-                               buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n"); 
+                               buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n"); 
                        }
                }
                return buffer.toString();
@@ -141,21 +145,22 @@ 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++) {
-                       if (x > 0) {
+               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(",");
                                }
-                               Object o = token_3_arrayValues[getValueIndex(x, y)];
-                               b.append(getConstantText(o));
-                       }
-               }
+                               Object o = token_3_arrayValues[getValueIndex(x, y)];
+                               b.append(getConstantText(o));
+                       }
+                 }
                b.append("}");
                return b.toString();
        }
@@ -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) {
@@ -186,13 +190,13 @@ public class ArrayPtg extends Ptg {
        }
        
        public Object clone() {
-               ArrayPtg ptg = new ArrayPtg();
-               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;
+         ArrayPtg ptg = new ArrayPtg();
+         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;
        }
 }
index 4aee71fbd444f4aec0b9edf010800fb7ab42d8d0..0da20a99ef3780261f21936107562fc148d2c2a1 100644 (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;
@@ -289,12 +287,6 @@ public final class AttrPtg extends OperationPtg {
       }
       return "UNKNOWN ATTRIBUTE";
      }
-    
-    
-    public byte getDefaultOperandClass() {
-        return Ptg.CLASS_VALUE;
-    }
 
     public Object clone() {
         int[] jt;
index 80c9f39d79c2f5816363c8944e99948af52cfdb1..e3342a03396d342b6a2a7cbbf4ec62f636e86a08 100644 (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;
index 951872f43b9f99e1abd858bd5389ed45f82b024e..e77382a34a4b0af2258b419139a68c3a047299b0 100644 (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;
     
index 52c6836198ba372041683024386b76b7a8c52ae5..90c1965909066d6c7fcfab29471513f928585a90 100644 (file)
    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;
+    }
 }
index 70fa62e58badef1554e704b522cd84d46de2f42e..60efad4f6a47097c0cd298056196bda1d5884bcb 100644 (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;
 
index a08a863d1c8046de0ecdd7d06c8b802acb9eb288..b8023d845520a417e9e00764d602d6cd92dc2926 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -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;
 
index a16992f94385d0ee49586e07be58e163c9295cdb..650ba054f659ad7e37064a50d2bed4ce29ccdb52 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -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);
     }
index 0cd54e5f55f827067b47ee4ac31f62aa81e3d32e..c4a0c33feec6f3dd8c875ea465bf17306fdb24d7 100644 (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;
@@ -52,7 +50,7 @@ public class ExpPtg
       field_1_first_row = in.readShort();
       field_2_first_col = in.readShort();
     }
-
+    
     public void writeBytes(byte [] array, int offset)
     {
       array[offset+0]= (byte) (sid);
@@ -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;
index 364ddf5a02bb46abb9030559394ccba816e2e47e..cea44ed430d7bcd40cb8c154dca037f2460aff3b 100644 (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;
index 431dc5717b820969f231bf436ee9a5aab4139b97..e3d2e77310bbb0c8f6b0456671f58d28a30cabc8 100644 (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();
+        }
     }
 
     /**
index 677d78c3e5c665380cba4e5ae10e656b2ac0cdb3..652c454ec41941899ccb74a95776108eb5e6d11e 100755 (executable)
@@ -1,4 +1,3 @@
-        
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    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;
 
index 6501203edcc9b070d4dabd1e8fbe2f44f818174b..44a1d0e8eaa31e002a83dce26d8a72a0ac5d2b20 100644 (file)
    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
index f3dd16f068a6750bf69c8238742f2bf8bf71fd3f..89c806dd2ef0e5e548a05f7f2b068bb5a85d001c 100644 (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);
index 8f5bddc190b6a3c5107c9e10a059f01f25621c28..27e7ec4f9174d5456070caf77c9c3ecbe9881e25 100644 (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()
     {
index f42966394b749f8fb9306e8f8406cc6e802af79e..fad0b90f5888947d4ad4b8969835d63b326b21e4 100755 (executable)
@@ -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;
 
index c23658d2db4302995e5c2baa2d779d929d1f892b..d1c6c55817880c26b01c63e49a4f106a3fa0c935 100644 (file)
    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
index ec33d10921475187d5234ccd5d01372781b597dd..98e217289bcf3f7f81f640a6dd516abb84e69d73 100644 (file)
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    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;
index 63c07a79e71def40c614e648255b4120ccb65167..020b90fc5c90c3e434258152d205fce56038417d 100644 (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;
index d539405cd061c899349d9b6e8ac14909464b8f02..a08090c8573290fc8f599516ff227a9381fc2332 100644 (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;
@@ -59,8 +57,6 @@ public class MissingArgPtg
     {
         return " ";
     }
-    
-    public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
         
     public Object clone() {
       return new MissingArgPtg();
index cbc0b6700216df9d0f7cb1c049e2a7527d058bda..1960dc90759bc5d67e661859507067e6783bcbb3 100644 (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;
 
index 9d93f1e9827bb4b4df60745d3c041dfe645a8fb1..f3bfd8ba2642282ae19ac9b5b14009bf7b5c424f 100644 (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 */
index 3036800b1032f89b5fe11070ba5abde16fc0e89c..2c95ba3afca291c541767393be7737e51c1e77fa 100644 (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
index 5dbbec875494e01c85d6cebbb59bac1008abb653..273edc01d1955b6e34fb4076b66c136cd08637e1 100755 (executable)
@@ -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;
 
index 8ec67345b41d7f5137ce7e127cc12534d5731458..f5e4305ccb2030c1332bad2edbef1a2bad75558a 100644 (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();
diff --git a/src/java/org/apache/poi/hssf/record/formula/OperandPtg.java b/src/java/org/apache/poi/hssf/record/formula/OperandPtg.java
new file mode 100644 (file)
index 0000000..02a708f
--- /dev/null
@@ -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;
+       }
+}
index 402dbd377428b0900cd39b5737f107f4212082eb..4cd5b57279bef2f25dac8f3a2203ad2218c2eff9 100644 (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 "()";
@@ -80,8 +68,6 @@ public class ParenthesisPtg
     public String toFormulaString(String[] operands) {
         return "("+operands[0]+")";
     }  
-    
-    public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
         
     public Object clone() {
       return new ParenthesisPtg();
index 0c59bb7acb55a6d90ba025a8e6cc2b5842a85f49..aa1e87765acec4bcc7c41e5342e1206cb7baf540 100644 (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();
     }
index 0dbb3ba283991e9473c78c0e2a76345ec70fc635..8d849fba2e1fd57afb225d462fd7a968aed24b62 100644 (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;
 
index fe8702c4abe789b680407c32133652eddb18ee5c..28d5d13b4e84e77f37f9815339d2ef9ed42a0c45 100644 (file)
@@ -119,254 +119,14 @@ public abstract class Ptg
         return stack;
     }
 
-    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 + ")");
+    public static Ptg createPtg(RecordInputStream in) {
+        byte id = in.readByte();
+        
+        if (id < 0x20) {
+               return createBasePtg(id, in);
         }
+        
+        Ptg  retval = createClassifiedPtg(id, in);
 
         if (id > 0x60) {
             retval.setClass(CLASS_ARRAY);
@@ -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,7 +280,15 @@ 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()
     {
@@ -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();
 }
index 4726a70c17265db0b1f454c7ec07d039438099fa..37ae53716d315517096a5561bd81f029c43a95a2 100644 (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()
     {
index 3b4749c855d926f91176c9ca16e3524aa70e9862..1731f658ea5282594ae2d37d3f157cfb473ccc83 100644 (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;
index c29b55bf94948dc9a61ec98931f95816eaf2862d..309744d784493c06c8f75c6633dbd83c044f075e 100755 (executable)
@@ -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;
index 5fc7eaf8a3eb1d98dde45e311256368a28a7dd98..1af278a9b1a8ca2088f148cb8c819b8e30ba4b63 100644 (file)
@@ -30,14 +30,14 @@ 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)
-     * 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.  
+     * 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() {
@@ -46,14 +46,14 @@ public class ReferencePtg extends Ptg {
 
     private final static int SIZE = 5;
     public final static byte sid  = 0x24;
-    private final static int MAX_ROW_NUMBER = 65536;             
+    private final static int MAX_ROW_NUMBER = 65536;
 
    /** The row index - zero based unsigned 16 bit value */
     private int            field_1_row;
-    /** Field 2 
-     * - lower 8 bits is the zero based unsigned byte column index 
+    /** Field 2
+     * - lower 8 bits is the zero based unsigned byte column index
      * - bit 16 - isRowRelative
-     * - bit 15 - isColumnRelative 
+     * - bit 15 - isColumnRelative
      */
     private int            field_2_col;
     private static final BitField         rowRelative = BitFieldFactory.getInstance(0x8000);
@@ -63,9 +63,9 @@ public class ReferencePtg extends Ptg {
     protected ReferencePtg() {
       //Required for clone methods
     }
-    
+
     /**
-     * Takes in a String represnetation of a cell reference and fills out the 
+     * Takes in a String represnetation of a cell reference and fills out the
      * numeric fields.
      */
     public ReferencePtg(String cellref) {
@@ -75,13 +75,13 @@ public class ReferencePtg extends Ptg {
         setColRelative(!c.isColAbsolute());
         setRowRelative(!c.isRowAbsolute());
     }
-    
+
     public ReferencePtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
       setRow(row);
       setColumn(column);
       setRowRelative(isRowRelative);
       setColRelative(isColumnRelative);
-    }    
+    }
 
     /** Creates new ValueReferencePtg */
 
@@ -90,22 +90,19 @@ public class ReferencePtg extends Ptg {
         field_1_row = in.readUShort();
         field_2_col = in.readUShort();
     }
-    
+
     public String getRefPtgName() {
       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)
@@ -147,16 +144,16 @@ public class ReferencePtg extends Ptg {
     {
         return rowRelative.isSet(field_2_col);
     }
-    
+
     public void setRowRelative(boolean rel) {
         field_2_col=rowRelative.setBoolean(field_2_col,rel);
     }
-    
+
     public boolean isColRelative()
     {
         return colRelative.isSet(field_2_col);
     }
-    
+
     public void setColRelative(boolean rel) {
         field_2_col=colRelative.setBoolean(field_2_col,rel);
     }
@@ -193,11 +190,11 @@ public class ReferencePtg extends Ptg {
         //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() {
         return Ptg.CLASS_REF;
     }
-    
+
     public Object clone() {
       ReferencePtg ptg = new ReferencePtg();
       ptg.field_1_row = field_1_row;
diff --git a/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java b/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java
new file mode 100644 (file)
index 0000000..43b8c13
--- /dev/null
@@ -0,0 +1,31 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hssf.record.formula;\r
+\r
+/**\r
+ * @author Josh Micich\r
+ */\r
+abstract class ScalarConstantPtg extends Ptg {\r
+       public boolean isBaseToken() {\r
+               return true;\r
+       }\r
+    public final byte getDefaultOperandClass() {\r
+        return Ptg.CLASS_VALUE;\r
+    }\r
+       \r
+}\r
index 47bd6ab6e863e82c6b05c35ed51df68af8dfc18e..14ed38203d5bdb027fe4d7e001398e3d159f152e 100644 (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;
index 37af74ba9ec2e1eee8b9eb2101e40434e8670992..3d04a9f45acff1900b16b515a1153a0c6b96fd60 100644 (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;
 
index 7c134b97d136f677d39b3d64ecdac5b138f03f19..51cb7018dfce8acc88ca73287dfed3cbc3ceabd9 100644 (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();
     }
index 148c83fa4157535599750fc76bbfb33c33da10ae..70cdbf2ca81cdca5415250aa0585d05aa9cfaae7 100644 (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();
     }
index 8d00ec34dff3a5f111b82fe20542f14d2f257625..c1fe011b5a272bb68659aacbfb4066218ba83932 100644 (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()
     {
index 56493d906ab0104300334364333159046b73029e..c686715905a42964c2b71cb92d8e5faeeb253516 100644 (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)
     {
     }
diff --git a/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java b/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java
new file mode 100644 (file)
index 0000000..4ef6ab5
--- /dev/null
@@ -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;
+       }
+}
index cf4f83b311c40ba583c76078e7cc28bdbeeba558..e23a58c59516c9a1494acdeda31c6045c660836b 100644 (file)
@@ -342,28 +342,28 @@ 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) { 
-               // named ranges, macro functions
+                // named ranges, macro functions
                 NamePtg namePtg = (NamePtg) ptg;
                 stack.push(new NameEval(namePtg.getIndex()));
                 continue; 
             }
             if (ptg instanceof NameXPtg) {
-               // TODO - external functions
+                // TODO - external functions
                 continue;
             }
             if (ptg instanceof UnknownPtg) { continue; }
@@ -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);