1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   /*
57    * Ptg.java
58    *
59    * Created on October 28, 2001, 6:30 PM
60    */
61   package org.apache.poi.hssf.record.formula;
62   
63   import java.util.List;
64   import java.util.ArrayList;
65   
66   import org.apache.poi.hssf.util.SheetReferences;
67   
68   /**
69    *
70    * @author  andy
71    * @author avik
72    * @author Jason Height (jheight at chariot dot net dot au)
73    */
74   
75   public abstract class Ptg
76   {
77   
78           
79       /** convert infix order ptg list to rpn order ptg list
80        * @return List ptgs in RPN order
81        * @param infixPtgs List of ptgs in infix order
82        */
83       
84       /* DO NOT REMOVE
85        *we keep this method in case we wish to change the way we parse
86        *It needs a getPrecedence in OperationsPtg
87       
88       public static List ptgsToRpn(List infixPtgs) {
89           java.util.Stack operands = new java.util.Stack();
90           java.util.List retval = new java.util.Stack();
91           
92           java.util.ListIterator i = infixPtgs.listIterator();
93           Object p;
94           OperationPtg o ;
95           boolean weHaveABracket = false;
96           while (i.hasNext()) {
97               p=i.next();
98               if (p instanceof OperationPtg) {
99                   if (p instanceof ParenthesisPtg) {
100                      if (!weHaveABracket) {
101                          operands.push(p);
102                          weHaveABracket = true;
103                      } else {
104                          o = (OperationPtg) operands.pop();
105                          while (!(o instanceof ParenthesisPtg)) { 
106                              retval.add(o);
107                          }
108                          weHaveABracket = false;
109                      }
110                  } else {
111                      
112                      while  (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative
113                          retval.add(operands.pop());
114                      }
115                      operands.push(p);
116                  }
117              } else {
118                  retval.add(p);
119              }
120          }
121          while (!operands.isEmpty()) {
122              if (operands.peek() instanceof ParenthesisPtg ){
123                  //throw some error
124              } else {
125                  retval.add(operands.pop());
126              }   
127          }
128          return retval;
129      }
130      */
131      
132      public static Ptg createPtg(byte [] data, int offset)
133      {
134          byte id     = data[ offset + 0 ];
135          Ptg  retval = null;
136  
137          final byte valueRef = ReferencePtg.sid + 0x20;
138          final byte arrayRef = ReferencePtg.sid + 0x40;
139          final byte valueFunc = FuncPtg.sid + 0x20;
140          final byte arrayFunc = FuncPtg.sid + 0x40;
141          final byte valueFuncVar = FuncVarPtg.sid +0x20;
142          final byte arrayFuncVar = FuncVarPtg.sid+0x40;
143          final byte valueArea = AreaPtg.sid + 0x20;
144          final byte arrayArea = AreaPtg.sid + 0x40;
145  
146          switch (id)
147          {
148              case AddPtg.sid :
149                  retval = new AddPtg(data, offset);
150                  break;
151  
152              case SubtractPtg.sid :
153                  retval = new SubtractPtg(data, offset);
154                  break;
155  
156              case BoolPtg.sid:
157                 retval = new BoolPtg(data, offset);
158                 break;
159  
160              case IntPtg.sid :
161                  retval = new IntPtg(data, offset);
162                  break;
163  
164              case DividePtg.sid :
165                  retval = new DividePtg(data, offset);
166                  break;
167  
168              case MultiplyPtg.sid :
169                  retval = new MultiplyPtg(data, offset);
170                  break;
171  
172              case PowerPtg.sid :
173                  retval = new PowerPtg(data, offset);
174                  break;
175   
176              case EqualPtg.sid:
177                  retval = new EqualPtg(data, offset);
178                  break;
179                  
180              case ConcatPtg.sid :
181                  retval = new ConcatPtg(data, offset);
182                  break;
183  
184              case AreaPtg.sid :
185                  retval = new AreaPtg(data, offset);
186                  break;
187              case valueArea:
188                  retval = new AreaPtg(data, offset);
189                  break;
190              case arrayArea:
191                  retval = new AreaPtg(data, offset);
192                  break;
193              case MemErrPtg.sid :        // 0x27       These 3 values 
194              case MemErrPtg.sid+0x20 :   // 0x47       documented in 
195              case MemErrPtg.sid+0x40 :   // 0x67       openOffice.org doc.
196                  retval = new MemErrPtg(data, offset);
197                  break;
198  
199              case AttrPtg.sid :
200                  retval = new AttrPtg(data, offset);
201                  break;
202                  
203              case ReferencePtg.sid :
204                  retval = new ReferencePtg(data, offset);
205                  break;   
206              case valueRef :
207                  retval = new ReferencePtg(data, offset);
208                  break;   
209              case arrayRef :
210                  retval = new ReferencePtg(data, offset);
211                  break;   
212  
213              case ParenthesisPtg.sid :
214                  retval = new ParenthesisPtg(data, offset);
215                  break;
216  
217              case MemFuncPtg.sid :
218                  retval = new MemFuncPtg(data, offset);
219                  break;
220  
221              case UnionPtg.sid :
222                  retval = new UnionPtg(data, offset);
223                  break;
224  
225              case FuncPtg.sid :
226                  retval = new FuncPtg(data, offset);
227                  break;
228                  
229              case valueFunc :
230                  retval = new FuncPtg(data, offset);
231                  break;
232              case arrayFunc :
233                  retval = new FuncPtg(data, offset);
234                  break;
235  
236              case FuncVarPtg.sid :
237                  retval = new FuncVarPtg(data, offset);
238                  break;
239                  
240              case valueFuncVar :
241                  retval = new FuncVarPtg(data, offset);
242                  break;
243              case arrayFuncVar :
244                  retval = new FuncVarPtg(data, offset);
245                  break;
246                  
247              case NumberPtg.sid :
248                 retval = new NumberPtg(data, offset);
249                 break;
250  
251              case StringPtg.sid :
252                 retval = new StringPtg(data, offset);
253                 break;
254  
255              case NamePtg.sid :            // 0x23     These 3 values
256              case NamePtg.sid+0x20 :       // 0x43     documented in
257              case NamePtg.sid+0x40 :       // 0x63     openOffice.org doc.
258  
259                  retval = new NamePtg(data, offset);
260                  break;
261  
262              case ExpPtg.sid :
263                  retval = new ExpPtg(data, offset);
264                  break;
265  
266              case Area3DPtg.sid :          // 0x3b     These 3 values 
267               case Area3DPtg.sid+0x20 :     // 0x5b     documented in 
268               case Area3DPtg.sid+0x40 :     // 0x7b     openOffice.org doc.
269  
270                  retval = new Area3DPtg(data, offset);
271                  break;
272  
273              case Ref3DPtg.sid:            // 0x3a     These 3 values 
274               case Ref3DPtg.sid+0x20:       // 0x5a     documented in 
275               case Ref3DPtg.sid+0x40:       // 0x7a     openOffice.org doc.
276  
277                  retval = new Ref3DPtg(data, offset);
278                  break;
279                  
280              case MissingArgPtg.sid:
281                  retval = new MissingArgPtg(data,offset);
282                  break;
283  
284              default :
285  
286                   //retval = new UnknownPtg();
287                   throw new java.lang.UnsupportedOperationException(
288                          Integer.toHexString(( int ) id) + " (" + ( int ) id + ")");
289          }
290          
291          if (id > 0x60) {
292              retval.setClass(CLASS_ARRAY);
293          } else if (id > 0x40) {
294              retval.setClass(CLASS_VALUE);
295          } else 
296              retval.setClass(CLASS_REF);
297         return retval;
298          
299      }
300  
301      public abstract int getSize();
302  
303      public final byte [] getBytes()
304      {
305          int    size  = getSize();
306          byte[] bytes = new byte[ size ];
307  
308          writeBytes(bytes, 0);
309          return bytes;
310      }
311      /** write this Ptg to a byte array*/
312      public abstract void writeBytes(byte [] array, int offset);
313      
314      /**
315       * return a string representation of this token alone
316       */
317      public abstract String toFormulaString(SheetReferences refs);
318      /**
319       * dump a debug representation (hexdump) to a string
320       */
321      public String toDebugString() {
322          byte[] ba = new byte[getSize()];
323          String retval=null;
324          writeBytes(ba,0);        
325          try {
326              retval = org.apache.poi.util.HexDump.dump(ba,0,0);
327          } catch (Exception e) {
328              e.printStackTrace();
329          }
330          return retval;
331      }
332      
333      public static final byte CLASS_REF = 0x00;
334      public static final byte CLASS_VALUE = 0x20;
335      public static final byte CLASS_ARRAY = 0x40;
336      
337      protected byte ptgClass = CLASS_REF; //base ptg
338      
339      public void setClass(byte thePtgClass) {
340          ptgClass = thePtgClass;
341      }
342      
343      /** returns the class (REF/VALUE/ARRAY) for this Ptg */
344      public byte getPtgClass() {
345          return ptgClass;
346      }
347      
348      public abstract byte getDefaultOperandClass();
349  
350      public abstract Object clone();
351  
352      
353      
354  }
355