2002-01-30 21:22:28 -05:00
/ * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2006-12-22 14:18:16 -05:00
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
2004-04-09 09:05:39 -04:00
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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * /
2002-01-30 21:22:28 -05:00
package org.apache.poi.hssf.record.formula ;
2002-04-18 08:00:53 -04:00
import java.util.List ;
import java.util.ArrayList ;
2006-01-21 00:40:07 -05:00
import java.util.Stack ;
2002-04-18 08:00:53 -04:00
2003-08-31 02:16:57 -04:00
import org.apache.poi.hssf.model.Workbook ;
2005-08-18 03:06:44 -04:00
import org.apache.poi.hssf.record.RecordInputStream ;
2002-07-14 20:14:40 -04:00
2002-01-30 21:22:28 -05:00
/ * *
*
* @author andy
2002-05-27 17:00:12 -04:00
* @author avik
2002-09-04 20:26:28 -04:00
* @author Jason Height ( jheight at chariot dot net dot au )
2002-01-30 21:22:28 -05:00
* /
public abstract class Ptg
{
2004-08-23 04:52:54 -04:00
2005-01-01 20:00:53 -05:00
/ * convert infix order ptg list to rpn order ptg list
2004-08-23 04:52:54 -04:00
* @return List ptgs in RPN order
* @param infixPtgs List of ptgs in infix order
* /
2002-04-29 20:18:29 -04:00
2002-04-30 19:22:27 -04:00
/ * DO NOT REMOVE
2002-04-29 20:18:29 -04:00
* we keep this method in case we wish to change the way we parse
* It needs a getPrecedence in OperationsPtg
2002-04-27 10:07:53 -04:00
public static List ptgsToRpn ( List infixPtgs ) {
java . util . Stack operands = new java . util . Stack ( ) ;
java . util . List retval = new java . util . Stack ( ) ;
java . util . ListIterator i = infixPtgs . listIterator ( ) ;
Object p ;
OperationPtg o ;
boolean weHaveABracket = false ;
while ( i . hasNext ( ) ) {
p = i . next ( ) ;
if ( p instanceof OperationPtg ) {
if ( p instanceof ParenthesisPtg ) {
if ( ! weHaveABracket ) {
operands . push ( p ) ;
weHaveABracket = true ;
} else {
o = ( OperationPtg ) operands . pop ( ) ;
while ( ! ( o instanceof ParenthesisPtg ) ) {
retval . add ( o ) ;
}
weHaveABracket = false ;
}
} else {
while ( ! operands . isEmpty ( ) & & ( ( OperationPtg ) operands . peek ( ) ) . getPrecedence ( ) > = ( ( OperationPtg ) p ) . getPrecedence ( ) ) { //TODO handle ^ since it is right associative
retval . add ( operands . pop ( ) ) ;
}
operands . push ( p ) ;
}
} else {
retval . add ( p ) ;
}
}
while ( ! operands . isEmpty ( ) ) {
if ( operands . peek ( ) instanceof ParenthesisPtg ) {
//throw some error
} else {
retval . add ( operands . pop ( ) ) ;
}
}
return retval ;
}
2002-04-29 20:18:29 -04:00
* /
2006-01-21 00:40:07 -05:00
public static Stack createParsedExpressionTokens ( short size , RecordInputStream in )
{
Stack stack = new Stack ( ) ;
int pos = 0 ;
List arrayPtgs = null ;
while ( pos < size )
{
Ptg ptg = Ptg . createPtg ( in ) ;
if ( ptg instanceof ArrayPtg ) {
if ( arrayPtgs = = null )
arrayPtgs = new ArrayList ( 5 ) ;
arrayPtgs . add ( ptg ) ;
pos + = 8 ;
} else pos + = ptg . getSize ( ) ;
stack . push ( ptg ) ;
}
if ( arrayPtgs ! = null ) {
for ( int i = 0 ; i < arrayPtgs . size ( ) ; i + + ) {
ArrayPtg p = ( ArrayPtg ) arrayPtgs . get ( i ) ;
p . readTokenValues ( in ) ;
}
}
return stack ;
}
2002-05-06 14:23:24 -04:00
2006-07-25 10:30:34 -04:00
public static Ptg createPtg ( RecordInputStream in )
2002-01-30 21:22:28 -05:00
{
2005-08-18 03:06:44 -04:00
byte id = in . readByte ( ) ;
2002-01-30 21:22:28 -05:00
Ptg retval = null ;
2002-05-27 17:00:12 -04:00
2002-01-30 21:22:28 -05:00
switch ( id )
{
2006-07-27 10:15:11 -04:00
case ExpPtg . sid : // 0x01
retval = new ExpPtg ( in ) ;
break ;
2002-09-02 17:16:29 -04:00
2006-07-27 10:15:11 -04:00
case AddPtg . sid : // 0x03
retval = new AddPtg ( in ) ;
2006-07-25 10:30:34 -04:00
break ;
2006-07-27 10:15:11 -04:00
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 ) ;
2003-07-25 16:11:27 -04:00
break ;
2006-07-27 10:15:11 -04:00
case AttrPtg . sid : // 0x19
retval = new AttrPtg ( in ) ;
break ;
case ErrPtg . sid : // 0x1c
retval = new ErrPtg ( in ) ;
break ;
case BoolPtg . sid : // 0x1d
retval = new BoolPtg ( in ) ;
2003-07-25 16:11:27 -04:00
break ;
2006-07-27 10:15:11 -04:00
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 ;
2002-04-23 18:24:41 -04:00
2002-01-30 21:22:28 -05:00
default :
2002-06-11 16:18:28 -04:00
//retval = new UnknownPtg();
2006-07-24 08:40:25 -04:00
throw new java . lang . UnsupportedOperationException ( " Unknown Ptg in Formula: 0x " +
2002-06-11 16:18:28 -04:00
Integer . toHexString ( ( int ) id ) + " ( " + ( int ) id + " ) " ) ;
2002-01-30 21:22:28 -05:00
}
2002-05-27 17:00:12 -04:00
if ( id > 0x60 ) {
retval . setClass ( CLASS_ARRAY ) ;
} else if ( id > 0x40 ) {
retval . setClass ( CLASS_VALUE ) ;
2006-07-27 10:15:11 -04:00
} else {
2002-05-27 17:00:12 -04:00
retval . setClass ( CLASS_REF ) ;
2006-07-27 10:15:11 -04:00
}
2002-05-27 17:00:12 -04:00
return retval ;
2002-04-20 19:42:10 -04:00
}
2006-01-21 00:40:07 -05:00
public static int serializePtgStack ( Stack expression , byte [ ] array , int offset ) {
int pos = 0 ;
int size = 0 ;
if ( expression ! = null )
size = expression . size ( ) ;
List arrayPtgs = null ;
for ( int k = 0 ; k < size ; k + + ) {
Ptg ptg = ( Ptg ) expression . get ( k ) ;
ptg . writeBytes ( array , pos + offset ) ;
if ( ptg instanceof ArrayPtg ) {
if ( arrayPtgs = = null )
arrayPtgs = new ArrayList ( 5 ) ;
arrayPtgs . add ( ptg ) ;
pos + = 8 ;
} else pos + = ptg . getSize ( ) ;
}
if ( arrayPtgs ! = null ) {
for ( int i = 0 ; i < arrayPtgs . size ( ) ; i + + ) {
ArrayPtg p = ( ArrayPtg ) arrayPtgs . get ( i ) ;
pos + = p . writeTokenValueBytes ( array , pos + offset ) ;
}
}
return pos ;
}
2002-01-30 21:22:28 -05:00
public abstract int getSize ( ) ;
public final byte [ ] getBytes ( )
{
int size = getSize ( ) ;
byte [ ] bytes = new byte [ size ] ;
writeBytes ( bytes , 0 ) ;
return bytes ;
}
2002-04-30 19:22:27 -04:00
/** write this Ptg to a byte array*/
2002-01-30 21:22:28 -05:00
public abstract void writeBytes ( byte [ ] array , int offset ) ;
2002-04-18 08:00:53 -04:00
2002-04-30 19:22:27 -04:00
/ * *
* return a string representation of this token alone
* /
2003-08-31 02:16:57 -04:00
public abstract String toFormulaString ( Workbook book ) ;
2002-04-29 21:05:49 -04:00
/ * *
2002-08-21 07:56:49 -04:00
* dump a debug representation ( hexdump ) to a string
2002-04-29 21:05:49 -04:00
* /
2002-04-29 23:05:07 -04:00
public String toDebugString ( ) {
2002-04-29 21:05:49 -04:00
byte [ ] ba = new byte [ getSize ( ) ] ;
String retval = null ;
writeBytes ( ba , 0 ) ;
try {
2002-08-21 07:56:49 -04:00
retval = org . apache . poi . util . HexDump . dump ( ba , 0 , 0 ) ;
2002-04-29 21:05:49 -04:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
2002-04-29 23:05:07 -04:00
return retval ;
2002-04-29 21:05:49 -04:00
}
2003-07-27 14:24:33 -04:00
/ * * Overridden toString method to ensure object hash is not printed .
* This helps get rid of gratuitous diffs when comparing two dumps
* Subclasses may output more relevant information by overriding this method
* * /
public String toString ( ) {
return this . getClass ( ) . toString ( ) ;
}
2002-05-27 17:00:12 -04:00
public static final byte CLASS_REF = 0x00 ;
public static final byte CLASS_VALUE = 0x20 ;
public static final byte CLASS_ARRAY = 0x40 ;
protected byte ptgClass = CLASS_REF ; //base ptg
public void setClass ( byte thePtgClass ) {
ptgClass = thePtgClass ;
}
2002-06-11 16:18:28 -04:00
/** returns the class (REF/VALUE/ARRAY) for this Ptg */
public byte getPtgClass ( ) {
return ptgClass ;
}
2002-05-27 17:00:12 -04:00
public abstract byte getDefaultOperandClass ( ) ;
2002-09-04 20:26:28 -04:00
public abstract Object clone ( ) ;
2002-05-27 17:00:12 -04:00
2002-04-18 08:00:53 -04:00
2002-01-30 21:22:28 -05:00
}