001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /*
018: * Created on May 14, 2005
019: *
020: */
021: package org.apache.poi.hssf.record.formula.eval;
022:
023: /**
024: * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
025: *
026: */
027: public class ValueEvalToNumericXlator {
028:
029: public static final int STRING_IS_PARSED = 0x0001;
030: public static final int BOOL_IS_PARSED = 0x0002;
031: public static final int BLANK_IS_PARSED = 0x0004; // => blanks are not ignored, converted to 0
032:
033: public static final int REF_STRING_IS_PARSED = 0x0008;
034: public static final int REF_BOOL_IS_PARSED = 0x0010;
035: public static final int REF_BLANK_IS_PARSED = 0x0020;
036:
037: public static final int EVALUATED_REF_STRING_IS_PARSED = 0x0040;
038: public static final int EVALUATED_REF_BOOL_IS_PARSED = 0x0080;
039: public static final int EVALUATED_REF_BLANK_IS_PARSED = 0x0100;
040:
041: public static final int STRING_TO_BOOL_IS_PARSED = 0x0200;
042: public static final int REF_STRING_TO_BOOL_IS_PARSED = 0x0400;
043:
044: public static final int STRING_IS_INVALID_VALUE = 0x0800;
045: public static final int REF_STRING_IS_INVALID_VALUE = 0x1000;
046:
047: // public static final int BOOL_IS_BLANK = 0x2000;
048: // public static final int REF_BOOL_IS_BLANK = 0x4000;
049: // public static final int STRING_IS_BLANK = 0x8000;
050: // public static final int REF_STRING_IS_BLANK = 0x10000;
051:
052: private final int flags;
053:
054: public ValueEvalToNumericXlator(int flags) {
055: this .flags = flags;
056: }
057:
058: /**
059: * returned value can be either A NumericValueEval, BlankEval or ErrorEval.
060: * The params can be either NumberEval, BoolEval, StringEval, or
061: * RefEval
062: * @param eval
063: */
064: public ValueEval attemptXlateToNumeric(ValueEval eval) {
065: ValueEval retval = null;
066:
067: if (eval == null) {
068: retval = BlankEval.INSTANCE;
069: }
070:
071: // most common case - least worries :)
072: else if (eval instanceof NumberEval) {
073: retval = (NumberEval) eval;
074: }
075:
076: // booleval
077: else if (eval instanceof BoolEval) {
078: retval = ((flags & BOOL_IS_PARSED) > 0) ? (NumericValueEval) eval
079: : xlateBlankEval(BLANK_IS_PARSED);
080: }
081:
082: // stringeval
083: else if (eval instanceof StringEval) {
084: retval = xlateStringEval((StringEval) eval); // TODO: recursive call needed
085: }
086:
087: // refeval
088: else if (eval instanceof RefEval) {
089: retval = xlateRefEval((RefEval) eval);
090: }
091:
092: // erroreval
093: else if (eval instanceof ErrorEval) {
094: retval = eval;
095: }
096:
097: else if (eval instanceof BlankEval) {
098: retval = xlateBlankEval(BLANK_IS_PARSED);
099: }
100:
101: // probably AreaEval? then not acceptable.
102: else {
103: throw new RuntimeException(
104: "Invalid ValueEval type passed for conversion: "
105: + eval.getClass());
106: }
107:
108: return retval;
109: }
110:
111: /**
112: * no args are required since BlankEval has only one
113: * instance. If flag is set, a zero
114: * valued numbereval is returned, else BlankEval.INSTANCE
115: * is returned.
116: */
117: private ValueEval xlateBlankEval(int flag) {
118: return ((flags & flag) > 0) ? (ValueEval) NumberEval.ZERO
119: : BlankEval.INSTANCE;
120: }
121:
122: /**
123: * uses the relevant flags to decode the supplied RefVal
124: * @param eval
125: */
126: private ValueEval xlateRefEval(RefEval reval) {
127: ValueEval retval = null;
128: ValueEval eval = (ValueEval) reval.getInnerValueEval();
129:
130: // most common case - least worries :)
131: if (eval instanceof NumberEval) {
132: retval = (NumberEval) eval;
133: }
134:
135: // booleval
136: else if (eval instanceof BoolEval) {
137: retval = ((flags & REF_BOOL_IS_PARSED) > 0) ? (ValueEval) eval
138: : BlankEval.INSTANCE;
139: }
140:
141: // stringeval
142: else if (eval instanceof StringEval) {
143: retval = xlateRefStringEval((StringEval) eval);
144: }
145:
146: // erroreval
147: else if (eval instanceof ErrorEval) {
148: retval = eval;
149: }
150:
151: // refeval
152: else if (eval instanceof RefEval) {
153: RefEval re = (RefEval) eval;
154: retval = xlateRefEval(re);
155: }
156:
157: else if (eval instanceof BlankEval) {
158: retval = xlateBlankEval(reval.isEvaluated() ? EVALUATED_REF_BLANK_IS_PARSED
159: : REF_BLANK_IS_PARSED);
160: }
161:
162: // probably AreaEval ? then not acceptable.
163: else {
164: throw new RuntimeException(
165: "Invalid ValueEval type passed for conversion: "
166: + eval.getClass());
167: }
168:
169: return retval;
170: }
171:
172: /**
173: * uses the relevant flags to decode the StringEval
174: * @param eval
175: */
176: private ValueEval xlateStringEval(StringEval eval) {
177: ValueEval retval = null;
178: if ((flags & STRING_IS_PARSED) > 0) {
179: String s = eval.getStringValue();
180: try {
181: double d = Double.parseDouble(s);
182: retval = new NumberEval(d);
183: } catch (Exception e) {
184: if ((flags & STRING_TO_BOOL_IS_PARSED) > 0) {
185: try {
186: boolean b = Boolean.getBoolean(s);
187: retval = b ? BoolEval.TRUE : BoolEval.FALSE;
188: } catch (Exception e2) {
189: retval = ErrorEval.VALUE_INVALID;
190: }
191: } else {
192: retval = ErrorEval.VALUE_INVALID;
193: }
194: }
195: } else if ((flags & STRING_TO_BOOL_IS_PARSED) > 0) {
196: String s = eval.getStringValue();
197: try {
198: boolean b = Boolean.getBoolean(s);
199: retval = b ? BoolEval.TRUE : BoolEval.FALSE;
200: } catch (Exception e) {
201: retval = ErrorEval.VALUE_INVALID;
202: }
203: }
204:
205: // strings are errors?
206: else if ((flags & STRING_IS_INVALID_VALUE) > 0) {
207: retval = ErrorEval.VALUE_INVALID;
208: }
209:
210: // ignore strings
211: else {
212: retval = xlateBlankEval(BLANK_IS_PARSED);
213: }
214: return retval;
215: }
216:
217: /**
218: * uses the relevant flags to decode the StringEval
219: * @param eval
220: */
221: private ValueEval xlateRefStringEval(StringEval eval) {
222: ValueEval retval = null;
223: if ((flags & REF_STRING_IS_PARSED) > 0) {
224: StringEval sve = (StringEval) eval;
225: String s = sve.getStringValue();
226: try {
227: double d = Double.parseDouble(s);
228: retval = new NumberEval(d);
229: } catch (Exception e) {
230: if ((flags & REF_STRING_TO_BOOL_IS_PARSED) > 0) {
231: try {
232: boolean b = Boolean.getBoolean(s);
233: retval = b ? BoolEval.TRUE : BoolEval.FALSE;
234: } catch (Exception e2) {
235: retval = ErrorEval.VALUE_INVALID;
236: }
237: } else {
238: retval = ErrorEval.VALUE_INVALID;
239: }
240: }
241: } else if ((flags & REF_STRING_TO_BOOL_IS_PARSED) > 0) {
242: StringEval sve = (StringEval) eval;
243: String s = sve.getStringValue();
244: try {
245: boolean b = Boolean.getBoolean(s);
246: retval = b ? BoolEval.TRUE : BoolEval.FALSE;
247: ;
248: } catch (Exception e) {
249: retval = ErrorEval.VALUE_INVALID;
250: }
251: }
252:
253: // strings are errors?
254: else if ((flags & REF_STRING_IS_INVALID_VALUE) > 0) {
255: retval = ErrorEval.VALUE_INVALID;
256: }
257:
258: // strings are blanks
259: else {
260: retval = BlankEval.INSTANCE;
261: }
262: return retval;
263: }
264:
265: }
|