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 IntPtg.sid :
157                  retval = new IntPtg(data, offset);
158                  break;
159  
160              case DividePtg.sid :
161                  retval = new DividePtg(data, offset);
162                  break;
163  
164              case MultiplyPtg.sid :
165                  retval = new MultiplyPtg(data, offset);
166                  break;
167  
168              case PowerPtg.sid :
169                  retval = new PowerPtg(data, offset);
170                  break;
171   
172              case EqualPtg.sid:
173                  retval = new EqualPtg(data, offset);
174                  break;
175                  
176              case ConcatPtg.sid :
177                  retval = new ConcatPtg(data, offset);
178                  break;
179  
180              case AreaPtg.sid :
181                  retval = new AreaPtg(data, offset);
182                  break;
183              case valueArea:
184                  retval = new AreaPtg(data, offset);
185                  break;
186              case arrayArea:
187                  retval = new AreaPtg(data, offset);
188                  break;
189              case MemErrPtg.sid :        // 0x27       These 3 values 
190              case MemErrPtg.sid+0x20 :   // 0x47       documented in 
191              case MemErrPtg.sid+0x40 :   // 0x67       openOffice.org doc.
192                  retval = new MemErrPtg(data, offset);
193                  break;
194  
195              case AttrPtg.sid :
196                  retval = new AttrPtg(data, offset);
197                  break;
198                  
199              case ReferencePtg.sid :
200                  retval = new ReferencePtg(data, offset);
201                  break;   
202              case valueRef :
203                  retval = new ReferencePtg(data, offset);
204                  break;   
205              case arrayRef :
206                  retval = new ReferencePtg(data, offset);
207                  break;   
208  
209              case ParenthesisPtg.sid :
210                  retval = new ParenthesisPtg(data, offset);
211                  break;
212  
213              case FuncPtg.sid :
214                  retval = new FuncPtg(data, offset);
215                  break;
216                  
217              case valueFunc :
218                  retval = new FuncPtg(data, offset);
219                  break;
220              case arrayFunc :
221                  retval = new FuncPtg(data, offset);
222                  break;
223                  
224              case FuncVarPtg.sid :
225                  retval = new FuncVarPtg(data, offset);
226                  break;
227                  
228              case valueFuncVar :
229                  retval = new FuncVarPtg(data, offset);
230                  break;
231              case arrayFuncVar :
232                  retval = new FuncVarPtg(data, offset);
233                  break;
234                  
235              case NumberPtg.sid :
236                 retval = new NumberPtg(data, offset);
237                 break;
238  
239              case StringPtg.sid :
240                 retval = new StringPtg(data, offset);
241                 break;
242  
243              case NamePtg.sid :            // 0x23     These 3 values
244              case NamePtg.sid+0x20 :       // 0x43     documented in
245              case NamePtg.sid+0x40 :       // 0x63     openOffice.org doc.
246  
247                  retval = new NamePtg(data, offset);
248                  break;
249  
250              case ExpPtg.sid :
251                  retval = new ExpPtg(data, offset);
252                  break;
253  
254              case Area3DPtg.sid :          // 0x3b     These 3 values 
255               case Area3DPtg.sid+0x20 :     // 0x5b     documented in 
256               case Area3DPtg.sid+0x40 :     // 0x7b     openOffice.org doc.
257  
258                  retval = new Area3DPtg(data, offset);
259                  break;
260  
261              case Ref3DPtg.sid:            // 0x3a     These 3 values 
262               case Ref3DPtg.sid+0x20:       // 0x5a     documented in 
263               case Ref3DPtg.sid+0x40:       // 0x7a     openOffice.org doc.
264  
265                  retval = new Ref3DPtg(data, offset);
266                  break;
267                  
268              case MissingArgPtg.sid:
269                  retval = new MissingArgPtg(data,offset);
270                  break;
271  
272              default :
273  
274                   //retval = new UnknownPtg();
275                   throw new java.lang.UnsupportedOperationException(
276                          Integer.toHexString(( int ) id) + " (" + ( int ) id + ")");
277          }
278          
279          if (id > 0x60) {
280              retval.setClass(CLASS_ARRAY);
281          } else if (id > 0x40) {
282              retval.setClass(CLASS_VALUE);
283          } else 
284              retval.setClass(CLASS_REF);
285         return retval;
286          
287      }
288  
289      public abstract int getSize();
290  
291      public final byte [] getBytes()
292      {
293          int    size  = getSize();
294          byte[] bytes = new byte[ size ];
295  
296          writeBytes(bytes, 0);
297          return bytes;
298      }
299      /** write this Ptg to a byte array*/
300      public abstract void writeBytes(byte [] array, int offset);
301      
302      /**
303       * return a string representation of this token alone
304       */
305      public abstract String toFormulaString(SheetReferences refs);
306      /**
307       * dump a debug representation (hexdump) to a string
308       */
309      public String toDebugString() {
310          byte[] ba = new byte[getSize()];
311          String retval=null;
312          writeBytes(ba,0);        
313          try {
314              retval = org.apache.poi.util.HexDump.dump(ba,0,0);
315          } catch (Exception e) {
316              e.printStackTrace();
317          }
318          return retval;
319      }
320      
321      public static final byte CLASS_REF = 0x00;
322      public static final byte CLASS_VALUE = 0x20;
323      public static final byte CLASS_ARRAY = 0x40;
324      
325      protected byte ptgClass = CLASS_REF; //base ptg
326      
327      public void setClass(byte thePtgClass) {
328          ptgClass = thePtgClass;
329      }
330      
331      /** returns the class (REF/VALUE/ARRAY) for this Ptg */
332      public byte getPtgClass() {
333          return ptgClass;
334      }
335      
336      public abstract byte getDefaultOperandClass();
337  
338      public abstract Object clone();
339  
340      
341      
342  }
343