KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > biff > formula > VariableArgFunction


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.biff.formula;
21
22 import java.util.Stack JavaDoc;
23
24 import common.Assert;
25 import common.Logger;
26
27 import jxl.WorkbookSettings;
28 import jxl.biff.IntegerHelper;
29
30 /**
31  * A built in function in a formula. These functions take a variable
32  * number of arguments, such as a range (eg. SUM etc)
33  */

34 class VariableArgFunction extends Operator implements ParsedThing
35 {
36   /**
37    * The logger
38    */

39   private static Logger logger = Logger.getLogger(VariableArgFunction.class);
40
41   /**
42    * The function
43    */

44   private Function function;
45
46   /**
47    * The number of arguments
48    */

49   private int arguments;
50
51   /**
52    * Flag which indicates whether this was initialized from the client
53    * api or from an excel sheet
54    */

55   private boolean readFromSheet;
56
57   /**
58    * The workbooks settings
59    */

60   private WorkbookSettings settings;
61
62   /**
63    * Constructor
64    */

65   public VariableArgFunction(WorkbookSettings ws)
66   {
67     readFromSheet = true;
68     settings = ws;
69   }
70
71   /**
72    * Constructor used when parsing a function from a string
73    *
74    * @param f the function
75    * @param a the number of arguments
76    */

77   public VariableArgFunction(Function f, int a, WorkbookSettings ws)
78   {
79     function = f;
80     arguments = a;
81     readFromSheet = false;
82     settings = ws;
83   }
84
85   /**
86    * Reads the ptg data from the array starting at the specified position
87    *
88    * @param data the RPN array
89    * @param pos the current position in the array, excluding the ptg identifier
90    * @return the number of bytes read
91    * @exception FormulaException
92    */

93   public int read(byte[] data, int pos) throws FormulaException
94   {
95     arguments = data[pos];
96     int index = IntegerHelper.getInt(data[pos+1], data[pos+2]);
97     function = Function.getFunction(index);
98
99     if (function == function.UNKNOWN)
100     {
101       throw new FormulaException(FormulaException.unrecognizedFunction, index);
102     }
103
104     return 3;
105   }
106
107   /**
108    * Gets the operands for this operator from the stack
109    */

110   public void getOperands(Stack JavaDoc s)
111   {
112     // parameters are in the correct order, god damn them
113
ParseItem[] items = new ParseItem[arguments];
114
115     for (int i = arguments - 1; i >= 0 ; i--)
116     {
117       ParseItem pi = (ParseItem) s.pop();
118       
119       items[i] = pi;
120     }
121
122     for (int i = 0 ; i < arguments; i++)
123     {
124       add(items[i]);
125     }
126   }
127
128   public void getString(StringBuffer JavaDoc buf)
129   {
130     buf.append(function.getName(settings));
131     buf.append('(');
132    
133     if (arguments > 0)
134     {
135       ParseItem[] operands = getOperands();
136       if (readFromSheet)
137       {
138         // arguments are in the same order they were specified
139
operands[0].getString(buf);
140         
141         for (int i = 1; i < arguments; i++)
142         {
143           buf.append(',');
144           operands[i].getString(buf);
145         }
146       }
147       else
148       {
149         // arguments are stored in the reverse order to which they
150
// were specified, so iterate through them backwards
151
operands[arguments - 1].getString(buf);
152         
153         for (int i = arguments - 2; i >= 0 ; i--)
154         {
155           buf.append(',');
156           operands[i].getString(buf);
157         }
158       }
159     }
160
161     buf.append(')');
162   }
163
164   /**
165    * Adjusts all the relative cell references in this formula by the
166    * amount specified. Used when copying formulas
167    *
168    * @param colAdjust the amount to add on to each relative cell reference
169    * @param rowAdjust the amount to add on to each relative row reference
170    */

171   public void adjustRelativeCellReferences(int colAdjust, int rowAdjust)
172   {
173     ParseItem[] operands = getOperands();
174
175     for (int i = 0 ; i < operands.length ; i++)
176     {
177       operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust);
178     }
179   }
180
181   /**
182    * Called when a column is inserted on the specified sheet. Tells
183    * the formula parser to update all of its cell references beyond this
184    * column
185    *
186    * @param sheetIndex the sheet on which the column was inserted
187    * @param col the column number which was inserted
188    * @param currentSheet TRUE if this formula is on the sheet in which the
189    * column was inserted, FALSE otherwise
190    */

191   void columnInserted(int sheetIndex, int col, boolean currentSheet)
192   {
193     ParseItem[] operands = getOperands();
194     for (int i = 0 ; i < operands.length ; i++)
195     {
196       operands[i].columnInserted(sheetIndex, col, currentSheet);
197     }
198   }
199
200   /**
201    * Called when a column is inserted on the specified sheet. Tells
202    * the formula parser to update all of its cell references beyond this
203    * column
204    *
205    * @param sheetIndex the sheet on which the column was removed
206    * @param col the column number which was removed
207    * @param currentSheet TRUE if this formula is on the sheet in which the
208    * column was inserted, FALSE otherwise
209    */

210   void columnRemoved(int sheetIndex, int col, boolean currentSheet)
211   {
212     ParseItem[] operands = getOperands();
213     for (int i = 0 ; i < operands.length ; i++)
214     {
215       operands[i].columnRemoved(sheetIndex, col, currentSheet);
216     }
217   }
218
219   /**
220    * Called when a column is inserted on the specified sheet. Tells
221    * the formula parser to update all of its cell references beyond this
222    * column
223    *
224    * @param sheetIndex the sheet on which the row was inserted
225    * @param row the row number which was inserted
226    * @param currentSheet TRUE if this formula is on the sheet in which the
227    * column was inserted, FALSE otherwise
228    */

229   void rowInserted(int sheetIndex, int row, boolean currentSheet)
230   {
231     ParseItem[] operands = getOperands();
232     for (int i = 0 ; i < operands.length ; i++)
233     {
234       operands[i].rowInserted(sheetIndex, row, currentSheet);
235     }
236   }
237
238   /**
239    * Called when a column is inserted on the specified sheet. Tells
240    * the formula parser to update all of its cell references beyond this
241    * column
242    *
243    * @param sheetIndex the sheet on which the row was removed
244    * @param row the row number which was removed
245    * @param currentSheet TRUE if this formula is on the sheet in which the
246    * column was inserted, FALSE otherwise
247    */

248   void rowRemoved(int sheetIndex, int row, boolean currentSheet)
249   {
250     ParseItem[] operands = getOperands();
251     for (int i = 0 ; i < operands.length ; i++)
252     {
253       operands[i].rowRemoved(sheetIndex, row, currentSheet);
254     }
255   }
256
257   /**
258    * Gets the underlying function
259    */

260   Function getFunction()
261   {
262     return function;
263   }
264
265   /**
266    * Gets the token representation of this item in RPN
267    *
268    * @return the bytes applicable to this formula
269    */

270   byte[] getBytes()
271   {
272     handleSpecialCases();
273
274     // Get the data for the operands - in the correct order
275
ParseItem[] operands = getOperands();
276     byte[] data = new byte[0];
277
278     for (int i = 0 ; i < operands.length ; i++)
279     {
280       byte[] opdata = operands[i].getBytes();
281
282       // Grow the array
283
byte[] newdata = new byte[data.length + opdata.length];
284       System.arraycopy(data, 0, newdata, 0, data.length);
285       System.arraycopy(opdata, 0, newdata, data.length, opdata.length);
286       data = newdata;
287     }
288
289     // Add on the operator byte
290
byte[] newdata = new byte[data.length + 4];
291     System.arraycopy(data, 0, newdata, 0, data.length);
292     newdata[data.length] = !useAlternateCode() ?
293       Token.FUNCTIONVARARG.getCode() : Token.FUNCTIONVARARG.getCode2() ;
294     newdata[data.length+1] = (byte) arguments;
295     IntegerHelper.getTwoBytes(function.getCode(), newdata, data.length+2);
296
297     return newdata;
298   }
299
300   /**
301    * Gets the precedence for this operator. Operator precedents run from
302    * 1 to 5, one being the highest, 5 being the lowest
303    *
304    * @return the operator precedence
305    */

306   int getPrecedence()
307   {
308     return 3;
309   }
310
311   /**
312    * Handles functions which form a special case
313    */

314   private void handleSpecialCases()
315   {
316     // Handle the array functions. Tell all the Area records to
317
// use their alternative token code
318
if (function == Function.SUMPRODUCT)
319     {
320       // Get the data for the operands - in reverse order
321
ParseItem[] operands = getOperands();
322       
323       for (int i = operands.length - 1 ; i >= 0 ; i--)
324       {
325         if (operands[i] instanceof Area)
326         {
327           operands[i].setAlternateCode();
328         }
329       }
330     }
331   }
332 }
333  
334
335
Popular Tags