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   /**
67    *
68    * @author  andy
69    * @author avik
70    */
71   
72   public abstract class Ptg
73   {
74   
75           
76       /** convert infix order ptg list to rpn order ptg list
77        * @return List ptgs in RPN order
78        * @param infixPtgs List of ptgs in infix order
79        */
80       
81       /* DO NOT REMOVE
82        *we keep this method in case we wish to change the way we parse
83        *It needs a getPrecedence in OperationsPtg
84       
85       public static List ptgsToRpn(List infixPtgs) {
86           java.util.Stack operands = new java.util.Stack();
87           java.util.List retval = new java.util.Stack();
88           
89           java.util.ListIterator i = infixPtgs.listIterator();
90           Object p;
91           OperationPtg o ;
92           boolean weHaveABracket = false;
93           while (i.hasNext()) {
94               p=i.next();
95               if (p instanceof OperationPtg) {
96                   if (p instanceof ParenthesisPtg) {
97                       if (!weHaveABracket) {
98                           operands.push(p);
99                           weHaveABracket = true;
100                      } else {
101                          o = (OperationPtg) operands.pop();
102                          while (!(o instanceof ParenthesisPtg)) { 
103                              retval.add(o);
104                          }
105                          weHaveABracket = false;
106                      }
107                  } else {
108                      
109                      while  (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative
110                          retval.add(operands.pop());
111                      }
112                      operands.push(p);
113                  }
114              } else {
115                  retval.add(p);
116              }
117          }
118          while (!operands.isEmpty()) {
119              if (operands.peek() instanceof ParenthesisPtg ){
120                  //throw some error
121              } else {
122                  retval.add(operands.pop());
123              }   
124          }
125          return retval;
126      }
127      */
128      
129      public static Ptg createPtg(byte [] data, int offset)
130      {
131          byte id     = data[ offset + 0 ];
132          Ptg  retval = null;
133  
134          final byte valueRef = ReferencePtg.sid + 0x20;
135          final byte arrayRef = ReferencePtg.sid + 0x40;
136          final byte valueFunc = FuncPtg.sid + 0x20;
137          final byte arrayFunc = FuncPtg.sid + 0x40;
138          final byte valueFuncVar = FuncVarPtg.sid +0x20;
139          final byte arrayFuncVar = FuncVarPtg.sid+0x40;
140          final byte valueArea = AreaPtg.sid + 0x20;
141          final byte arrayArea = AreaPtg.sid + 0x40;
142  
143          switch (id)
144          {
145              case AddPtg.sid :
146                  retval = new AddPtg(data, offset);
147                  break;
148  
149              case SubtractPtg.sid :
150                  retval = new SubtractPtg(data, offset);
151                  break;
152  
153              case IntPtg.sid :
154                  retval = new IntPtg(data, offset);
155                  break;
156  
157              case DividePtg.sid :
158                  retval = new DividePtg(data, offset);
159                  break;
160  
161              case MultiplyPtg.sid :
162                  retval = new MultiplyPtg(data, offset);
163                  break;
164  
165              case PowerPtg.sid :
166                  retval = new PowerPtg(data, offset);
167                  break;
168                  
169              case ConcatPtg.sid :
170                  retval = new ConcatPtg(data, offset);
171                  break;
172  
173              case AreaPtg.sid :
174                  retval = new AreaPtg(data, offset);
175                  break;
176              case valueArea:
177                  retval = new AreaPtg(data, offset);
178                  break;
179              case arrayArea:
180                  retval = new AreaPtg(data, offset);
181                  break;
182              case MemErrPtg.sid :        // 0x27       These 3 values 
183              case MemErrPtg.sid+0x20 :   // 0x47       documented in 
184              case MemErrPtg.sid+0x40 :   // 0x67       openOffice.org doc.
185                  retval = new MemErrPtg(data, offset);
186                  break;
187  
188              case AttrPtg.sid :
189                  retval = new AttrPtg(data, offset);
190                  break;
191                  
192              case ReferencePtg.sid :
193                  retval = new ReferencePtg(data, offset);
194                  break;   
195              case valueRef :
196                  retval = new ReferencePtg(data, offset);
197                  break;   
198              case arrayRef :
199                  retval = new ReferencePtg(data, offset);
200                  break;   
201  
202              case ParenthesisPtg.sid :
203                  retval = new ParenthesisPtg(data, offset);
204                  break;
205  
206              case FuncPtg.sid :
207                  retval = new FuncPtg(data, offset);
208                  break;
209                  
210              case valueFunc :
211                  retval = new FuncPtg(data, offset);
212                  break;
213              case arrayFunc :
214                  retval = new FuncPtg(data, offset);
215                  break;
216                  
217              case FuncVarPtg.sid :
218                  retval = new FuncVarPtg(data, offset);
219                  break;
220                  
221              case valueFuncVar :
222                  retval = new FuncVarPtg(data, offset);
223                  break;
224              case arrayFuncVar :
225                  retval = new FuncVarPtg(data, offset);
226                  break;
227                  
228              case NumberPtg.sid :
229                 retval = new NumberPtg(data, offset);
230                 break;
231  
232              case StringPtg.sid :
233                 retval = new StringPtg(data, offset);
234                 break;
235  
236              case NamePtg.sid :            // 0x23     These 3 values
237              case NamePtg.sid+0x20 :       // 0x43     documented in
238              case NamePtg.sid+0x40 :       // 0x63     openOffice.org doc.
239  
240                  retval = new NamePtg(data, offset);
241                  break;
242  
243              case ExpPtg.sid :
244                  retval = new ExpPtg(data, offset);
245                  break;
246  
247              case Area3DPtg.sid :          // 0x3b     These 3 values 
248               case Area3DPtg.sid+0x20 :     // 0x5b     documented in 
249               case Area3DPtg.sid+0x40 :     // 0x7b     openOffice.org doc.
250  
251                  retval = new Area3DPtg(data, offset);
252                  break;
253  
254              case Ref3DPtg.sid:            // 0x3a     These 3 values 
255               case Ref3DPtg.sid+0x20:       // 0x5a     documented in 
256               case Ref3DPtg.sid+0x40:       // 0x7a     openOffice.org doc.
257  
258                  retval = new Ref3DPtg(data, offset);
259                  break;
260                  
261              case MissingArgPtg.sid:
262                  retval = new MissingArgPtg(data,offset);
263                  break;
264  
265              default :
266  
267                   //retval = new UnknownPtg();
268                   throw new java.lang.UnsupportedOperationException(
269                          Integer.toHexString(( int ) id) + " (" + ( int ) id + ")");
270          }
271          
272          if (id > 0x60) {
273              retval.setClass(CLASS_ARRAY);
274          } else if (id > 0x40) {
275              retval.setClass(CLASS_VALUE);
276          } else 
277              retval.setClass(CLASS_REF);
278         return retval;
279          
280      }
281  
282      public abstract int getSize();
283  
284      public final byte [] getBytes()
285      {
286          int    size  = getSize();
287          byte[] bytes = new byte[ size ];
288  
289          writeBytes(bytes, 0);
290          return bytes;
291      }
292      /** write this Ptg to a byte array*/
293      public abstract void writeBytes(byte [] array, int offset);
294      
295      /**
296       * return a string representation of this token alone
297       */
298      public abstract String toFormulaString();
299      /**
300       * dump a debug representation (hexdump) to a strnig
301       */
302      public String toDebugString() {
303          byte[] ba = new byte[getSize()];
304          String retval=null;
305          writeBytes(ba,0);        
306          try {
307          retval = org.apache.poi.util.HexDump.dump(ba,0,0);       
308          } catch (Exception e) {
309              e.printStackTrace();
310          }
311          return retval;
312      }
313      
314      public static final byte CLASS_REF = 0x00;
315      public static final byte CLASS_VALUE = 0x20;
316      public static final byte CLASS_ARRAY = 0x40;
317      
318      protected byte ptgClass = CLASS_REF; //base ptg
319      
320      public void setClass(byte thePtgClass) {
321          ptgClass = thePtgClass;
322      }
323      
324      /** returns the class (REF/VALUE/ARRAY) for this Ptg */
325      public byte getPtgClass() {
326          return ptgClass;
327      }
328      
329      public abstract byte getDefaultOperandClass();
330  
331      
332      
333  }
334