xref: /AOO41X/main/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java (revision 7a3beb322b74df1b6c96e03605837df34781c68f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
25 
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.util.Vector;
29 import java.util.Enumeration;
30 
31 import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
32 
33 /**
34  * This Helper class provides a simplified interface to conversion between PocketXL formula representation
35  * and Calc formula representation.<p>
36  * The class is used by {@link org.openoffice.xmerge.converter.xml.sxc.pexcel.Records.Formula}
37  */
38 public class FormulaHelper {
39 
40     private static FormulaParser parser;
41     private static FormulaCompiler compiler;
42     private static TokenEncoder encoder;
43     private static TokenDecoder decoder;
44     private boolean rangeType = false;
45     private boolean expressionType = false;
46 
47     static {
48         parser   = new FormulaParser();
49         compiler = new FormulaCompiler();
50         encoder = new TokenEncoder();
51         decoder  = new TokenDecoder();
52     }
53 
54     /**
55      * Sets the workbook cache so that global data such as
56      * <code>DefinedNames</code>, <code>Boundsheets</code> can be read
57      *
58      * @param wb Wrokbook object containing all the global data
59      */
setWorkbook(Workbook wb)60     public void setWorkbook(Workbook wb) {
61 
62         encoder.setWorkbook(wb);
63         decoder.setWorkbook(wb);
64         parser.setWorkbook(wb);
65     }
66 
67     /**
68      * Convertes a string representation of a calc formula into an array of PocketXL bytes
69      * @param   formula The Formula String (e.g. 1+SUM(A1,B1))
70      *
71      * @throws  UnsupportedFunctionException    Thrown if a function in the formula is nto supported by Pocket Excel
72      * @throws  FormulaParsingException Thrown when the formula is not well formed
73      *
74      */
convertCalcToPXL(String formula)75     public byte[] convertCalcToPXL(String formula) throws UnsupportedFunctionException, FormulaParsingException {
76 
77         Vector parseTokens = parser.parse(formula);
78         Vector rpnTokens = compiler.infix2RPN(parseTokens);
79 
80         ByteArrayOutputStream bytes = null;
81         try {
82             bytes = new ByteArrayOutputStream();
83             for (Enumeration e = rpnTokens.elements(); e.hasMoreElements();) {
84                 Token t = (Token)e.nextElement();
85                 bytes.write(encoder.getByte(t));
86             }
87         } catch (IOException e) {
88         }
89 
90         return bytes.toByteArray();
91     }
92 
93     /**
94      * Converts a PocketXL byte array into a Calc function string
95      * @param   formula A byte array that contains the PocketXL bytes for a formula
96      *
97      */
convertPXLToCalc(byte[] formula)98     public String convertPXLToCalc(byte[] formula) {
99 
100         Vector parseTokens = decoder.getTokenVector(formula);
101         Vector infixTokens = compiler.RPN2Infix(parseTokens);
102 
103         StringBuffer buff = new StringBuffer();
104         for (Enumeration e = infixTokens.elements();e.hasMoreElements();) {
105             Token t = (Token)e.nextElement();
106             buff.append(t.toString());
107             // If we are parsing a Name definition we need to know if it is of
108             // type range or expression
109             if(!t.isOperand()) {
110                 expressionType = true;
111             }
112         }
113         if(!expressionType) {
114             rangeType = true;
115         }
116         return "=" + buff.toString();
117     }
118 
119     /**
120      * Returns a boolean indicating whether or not the byte[] parsed is of
121      * type range. This means it contains only a cell reference and no
122      * operators. This is necessry because the syntax for range and expression
123      * types differs. This is only of interest when dealing with
124      * <code>DefinedNames</code> and not <code>Formula</code>
125      *
126      * @return a boolean true if of type range otherwise false
127      *
128      */
isRangeType()129      public boolean isRangeType() {
130 
131         return rangeType;
132     }
133 
134     /**
135      * Returns a boolean indicating whether or not the byte[] parsed is of
136      * type expression. This means it contains operators. This is necessry
137      * because the syntax for range and expression types differs. This is
138      * only of interest when dealing with <code>DefinedNames</code> and not
139      * <code>Formula</code>
140      *
141      * @return a boolean true if of type expression otherwise false
142      *
143      */
isExpressionType()144      public boolean isExpressionType() {
145 
146         return expressionType;
147     }
148 }
149