whitespace
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1716057 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
58718f7245
commit
d58342dd9f
@ -27,302 +27,302 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public final class OperandResolver {
|
public final class OperandResolver {
|
||||||
|
|
||||||
// Based on regular expression defined in JavaDoc at {@link java.lang.Double#valueOf}
|
// Based on regular expression defined in JavaDoc at {@link java.lang.Double#valueOf}
|
||||||
// modified to remove support for NaN, Infinity, Hexadecimal support and floating type suffixes
|
// modified to remove support for NaN, Infinity, Hexadecimal support and floating type suffixes
|
||||||
private static final String Digits = "(\\p{Digit}+)";
|
private static final String Digits = "(\\p{Digit}+)";
|
||||||
private static final String Exp = "[eE][+-]?"+Digits;
|
private static final String Exp = "[eE][+-]?"+Digits;
|
||||||
private static final String fpRegex =
|
private static final String fpRegex =
|
||||||
("[\\x00-\\x20]*" +
|
("[\\x00-\\x20]*" +
|
||||||
"[+-]?(" +
|
"[+-]?(" +
|
||||||
"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
|
"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
|
||||||
"(\\.("+Digits+")("+Exp+")?))))"+
|
"(\\.("+Digits+")("+Exp+")?))))"+
|
||||||
"[\\x00-\\x20]*");
|
"[\\x00-\\x20]*");
|
||||||
|
|
||||||
|
|
||||||
private OperandResolver() {
|
private OperandResolver() {
|
||||||
// no instances of this class
|
// no instances of this class
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a single value from a variety of different argument types according to standard
|
* Retrieves a single value from a variety of different argument types according to standard
|
||||||
* Excel rules. Does not perform any type conversion.
|
* Excel rules. Does not perform any type conversion.
|
||||||
* @param arg the evaluated argument as passed to the function or operator.
|
* @param arg the evaluated argument as passed to the function or operator.
|
||||||
* @param srcCellRow used when arg is a single column AreaRef
|
* @param srcCellRow used when arg is a single column AreaRef
|
||||||
* @param srcCellCol used when arg is a single row AreaRef
|
* @param srcCellCol used when arg is a single row AreaRef
|
||||||
* @return a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt> or <tt>BlankEval</tt>.
|
* @return a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt> or <tt>BlankEval</tt>.
|
||||||
* Never <code>null</code> or <tt>ErrorEval</tt>.
|
* Never <code>null</code> or <tt>ErrorEval</tt>.
|
||||||
* @throws EvaluationException(#VALUE!) if srcCellRow or srcCellCol do not properly index into
|
* @throws EvaluationException(#VALUE!) if srcCellRow or srcCellCol do not properly index into
|
||||||
* an AreaEval. If the actual value retrieved is an ErrorEval, a corresponding
|
* an AreaEval. If the actual value retrieved is an ErrorEval, a corresponding
|
||||||
* EvaluationException is thrown.
|
* EvaluationException is thrown.
|
||||||
*/
|
*/
|
||||||
public static ValueEval getSingleValue(ValueEval arg, int srcCellRow, int srcCellCol)
|
public static ValueEval getSingleValue(ValueEval arg, int srcCellRow, int srcCellCol)
|
||||||
throws EvaluationException {
|
throws EvaluationException {
|
||||||
final ValueEval result;
|
final ValueEval result;
|
||||||
if (arg instanceof RefEval) {
|
if (arg instanceof RefEval) {
|
||||||
result = chooseSingleElementFromRef((RefEval) arg);
|
result = chooseSingleElementFromRef((RefEval) arg);
|
||||||
} else if (arg instanceof AreaEval) {
|
} else if (arg instanceof AreaEval) {
|
||||||
result = chooseSingleElementFromArea((AreaEval) arg, srcCellRow, srcCellCol);
|
result = chooseSingleElementFromArea((AreaEval) arg, srcCellRow, srcCellCol);
|
||||||
} else {
|
} else {
|
||||||
result = arg;
|
result = arg;
|
||||||
}
|
}
|
||||||
if (result instanceof ErrorEval) {
|
if (result instanceof ErrorEval) {
|
||||||
throw new EvaluationException((ErrorEval) result);
|
throw new EvaluationException((ErrorEval) result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements (some perhaps not well known) Excel functionality to select a single cell from an
|
* Implements (some perhaps not well known) Excel functionality to select a single cell from an
|
||||||
* area depending on the coordinates of the calling cell. Here is an example demonstrating
|
* area depending on the coordinates of the calling cell. Here is an example demonstrating
|
||||||
* both selection from a single row area and a single column area in the same formula.
|
* both selection from a single row area and a single column area in the same formula.
|
||||||
*
|
*
|
||||||
* <table border="1" cellpadding="1" cellspacing="1" summary="sample spreadsheet">
|
* <table border="1" cellpadding="1" cellspacing="1" summary="sample spreadsheet">
|
||||||
* <tr><th> </th><th> A </th><th> B </th><th> C </th><th> D </th></tr>
|
* <tr><th> </th><th> A </th><th> B </th><th> C </th><th> D </th></tr>
|
||||||
* <tr><th>1</th><td>15</td><td>20</td><td>25</td><td> </td></tr>
|
* <tr><th>1</th><td>15</td><td>20</td><td>25</td><td> </td></tr>
|
||||||
* <tr><th>2</th><td> </td><td> </td><td> </td><td>200</td></tr>
|
* <tr><th>2</th><td> </td><td> </td><td> </td><td>200</td></tr>
|
||||||
* <tr><th>3</th><td> </td><td> </td><td> </td><td>300</td></tr>
|
* <tr><th>3</th><td> </td><td> </td><td> </td><td>300</td></tr>
|
||||||
* <tr><th>3</th><td> </td><td> </td><td> </td><td>400</td></tr>
|
* <tr><th>3</th><td> </td><td> </td><td> </td><td>400</td></tr>
|
||||||
* </table>
|
* </table>
|
||||||
*
|
*
|
||||||
* If the formula "=1000+A1:B1+D2:D3" is put into the 9 cells from A2 to C4, the spreadsheet
|
* If the formula "=1000+A1:B1+D2:D3" is put into the 9 cells from A2 to C4, the spreadsheet
|
||||||
* will look like this:
|
* will look like this:
|
||||||
*
|
*
|
||||||
* <table border="1" cellpadding="1" cellspacing="1" summary="sample spreadsheet">
|
* <table border="1" cellpadding="1" cellspacing="1" summary="sample spreadsheet">
|
||||||
* <tr><th> </th><th> A </th><th> B </th><th> C </th><th> D </th></tr>
|
* <tr><th> </th><th> A </th><th> B </th><th> C </th><th> D </th></tr>
|
||||||
* <tr><th>1</th><td>15</td><td>20</td><td>25</td><td> </td></tr>
|
* <tr><th>1</th><td>15</td><td>20</td><td>25</td><td> </td></tr>
|
||||||
* <tr><th>2</th><td>1215</td><td>1220</td><td>#VALUE!</td><td>200</td></tr>
|
* <tr><th>2</th><td>1215</td><td>1220</td><td>#VALUE!</td><td>200</td></tr>
|
||||||
* <tr><th>3</th><td>1315</td><td>1320</td><td>#VALUE!</td><td>300</td></tr>
|
* <tr><th>3</th><td>1315</td><td>1320</td><td>#VALUE!</td><td>300</td></tr>
|
||||||
* <tr><th>4</th><td>#VALUE!</td><td>#VALUE!</td><td>#VALUE!</td><td>400</td></tr>
|
* <tr><th>4</th><td>#VALUE!</td><td>#VALUE!</td><td>#VALUE!</td><td>400</td></tr>
|
||||||
* </table>
|
* </table>
|
||||||
*
|
*
|
||||||
* Note that the row area (A1:B1) does not include column C and the column area (D2:D3) does
|
* Note that the row area (A1:B1) does not include column C and the column area (D2:D3) does
|
||||||
* not include row 4, so the values in C1(=25) and D4(=400) are not accessible to the formula
|
* not include row 4, so the values in C1(=25) and D4(=400) are not accessible to the formula
|
||||||
* as written, but in the 4 cells A2:B3, the row and column selection works ok.<p/>
|
* as written, but in the 4 cells A2:B3, the row and column selection works ok.<p/>
|
||||||
*
|
*
|
||||||
* The same concept is extended to references across sheets, such that even multi-row,
|
* The same concept is extended to references across sheets, such that even multi-row,
|
||||||
* multi-column areas can be useful.<p/>
|
* multi-column areas can be useful.<p/>
|
||||||
*
|
*
|
||||||
* Of course with carefully (or carelessly) chosen parameters, cyclic references can occur and
|
* Of course with carefully (or carelessly) chosen parameters, cyclic references can occur and
|
||||||
* hence this method <b>can</b> throw a 'circular reference' EvaluationException. Note that
|
* hence this method <b>can</b> throw a 'circular reference' EvaluationException. Note that
|
||||||
* this method does not attempt to detect cycles. Every cell in the specified Area <tt>ae</tt>
|
* this method does not attempt to detect cycles. Every cell in the specified Area <tt>ae</tt>
|
||||||
* has already been evaluated prior to this method call. Any cell (or cell<b>s</b>) part of
|
* has already been evaluated prior to this method call. Any cell (or cell<b>s</b>) part of
|
||||||
* <tt>ae</tt> that would incur a cyclic reference error if selected by this method, will
|
* <tt>ae</tt> that would incur a cyclic reference error if selected by this method, will
|
||||||
* already have the value <t>ErrorEval.CIRCULAR_REF_ERROR</tt> upon entry to this method. It
|
* already have the value <t>ErrorEval.CIRCULAR_REF_ERROR</tt> upon entry to this method. It
|
||||||
* is assumed logic exists elsewhere to produce this behaviour.
|
* is assumed logic exists elsewhere to produce this behaviour.
|
||||||
*
|
*
|
||||||
* @return whatever the selected cell's evaluated value is. Never <code>null</code>. Never
|
* @return whatever the selected cell's evaluated value is. Never <code>null</code>. Never
|
||||||
* <tt>ErrorEval</tt>.
|
* <tt>ErrorEval</tt>.
|
||||||
* @throws EvaluationException if there is a problem with indexing into the area, or if the
|
* @throws EvaluationException if there is a problem with indexing into the area, or if the
|
||||||
* evaluated cell has an error.
|
* evaluated cell has an error.
|
||||||
*/
|
*/
|
||||||
public static ValueEval chooseSingleElementFromArea(AreaEval ae,
|
public static ValueEval chooseSingleElementFromArea(AreaEval ae,
|
||||||
int srcCellRow, int srcCellCol) throws EvaluationException {
|
int srcCellRow, int srcCellCol) throws EvaluationException {
|
||||||
ValueEval result = chooseSingleElementFromAreaInternal(ae, srcCellRow, srcCellCol);
|
ValueEval result = chooseSingleElementFromAreaInternal(ae, srcCellRow, srcCellCol);
|
||||||
if (result instanceof ErrorEval) {
|
if (result instanceof ErrorEval) {
|
||||||
throw new EvaluationException((ErrorEval) result);
|
throw new EvaluationException((ErrorEval) result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return possibly <tt>ErrorEval</tt>, and <code>null</code>
|
* @return possibly <tt>ErrorEval</tt>, and <code>null</code>
|
||||||
*/
|
*/
|
||||||
private static ValueEval chooseSingleElementFromAreaInternal(AreaEval ae,
|
private static ValueEval chooseSingleElementFromAreaInternal(AreaEval ae,
|
||||||
int srcCellRow, int srcCellCol) throws EvaluationException {
|
int srcCellRow, int srcCellCol) throws EvaluationException {
|
||||||
|
|
||||||
// if(false) {
|
// if(false) {
|
||||||
// // this is too simplistic
|
// // this is too simplistic
|
||||||
// if(ae.containsRow(srcCellRow) && ae.containsColumn(srcCellCol)) {
|
// if(ae.containsRow(srcCellRow) && ae.containsColumn(srcCellCol)) {
|
||||||
// throw new EvaluationException(ErrorEval.CIRCULAR_REF_ERROR);
|
// throw new EvaluationException(ErrorEval.CIRCULAR_REF_ERROR);
|
||||||
// }
|
// }
|
||||||
// /*
|
// /*
|
||||||
// Circular references are not dealt with directly here, but it is worth noting some issues.
|
// Circular references are not dealt with directly here, but it is worth noting some issues.
|
||||||
//
|
//
|
||||||
// ANY one of the return statements in this method could return a cell that is identical
|
// ANY one of the return statements in this method could return a cell that is identical
|
||||||
// to the one immediately being evaluated. The evaluating cell is identified by srcCellRow,
|
// to the one immediately being evaluated. The evaluating cell is identified by srcCellRow,
|
||||||
// srcCellRow AND sheet. The sheet is not available in any nearby calling method, so that's
|
// srcCellRow AND sheet. The sheet is not available in any nearby calling method, so that's
|
||||||
// one reason why circular references are not easy to detect here. (The sheet of the returned
|
// one reason why circular references are not easy to detect here. (The sheet of the returned
|
||||||
// cell can be obtained from ae if it is an Area3DEval.)
|
// cell can be obtained from ae if it is an Area3DEval.)
|
||||||
//
|
//
|
||||||
// Another reason there's little value in attempting to detect circular references here is
|
// Another reason there's little value in attempting to detect circular references here is
|
||||||
// that only direct circular references could be detected. If the cycle involved two or more
|
// that only direct circular references could be detected. If the cycle involved two or more
|
||||||
// cells this method could not detect it.
|
// cells this method could not detect it.
|
||||||
//
|
//
|
||||||
// Logic to detect evaluation cycles of all kinds has been coded in EvaluationCycleDetector
|
// Logic to detect evaluation cycles of all kinds has been coded in EvaluationCycleDetector
|
||||||
// (and FormulaEvaluator).
|
// (and FormulaEvaluator).
|
||||||
// */
|
// */
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (ae.isColumn()) {
|
if (ae.isColumn()) {
|
||||||
if(ae.isRow()) {
|
if(ae.isRow()) {
|
||||||
return ae.getRelativeValue(0, 0);
|
return ae.getRelativeValue(0, 0);
|
||||||
}
|
}
|
||||||
if(!ae.containsRow(srcCellRow)) {
|
if(!ae.containsRow(srcCellRow)) {
|
||||||
throw EvaluationException.invalidValue();
|
throw EvaluationException.invalidValue();
|
||||||
}
|
}
|
||||||
return ae.getAbsoluteValue(srcCellRow, ae.getFirstColumn());
|
return ae.getAbsoluteValue(srcCellRow, ae.getFirstColumn());
|
||||||
}
|
}
|
||||||
if(!ae.isRow()) {
|
if(!ae.isRow()) {
|
||||||
// multi-column, multi-row area
|
// multi-column, multi-row area
|
||||||
if(ae.containsRow(srcCellRow) && ae.containsColumn(srcCellCol)) {
|
if(ae.containsRow(srcCellRow) && ae.containsColumn(srcCellCol)) {
|
||||||
return ae.getAbsoluteValue(ae.getFirstRow(), ae.getFirstColumn());
|
return ae.getAbsoluteValue(ae.getFirstRow(), ae.getFirstColumn());
|
||||||
}
|
}
|
||||||
throw EvaluationException.invalidValue();
|
throw EvaluationException.invalidValue();
|
||||||
}
|
}
|
||||||
if(!ae.containsColumn(srcCellCol)) {
|
if(!ae.containsColumn(srcCellCol)) {
|
||||||
throw EvaluationException.invalidValue();
|
throw EvaluationException.invalidValue();
|
||||||
}
|
}
|
||||||
return ae.getAbsoluteValue(ae.getFirstRow(), srcCellCol);
|
return ae.getAbsoluteValue(ae.getFirstRow(), srcCellCol);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ValueEval chooseSingleElementFromRef(RefEval ref) {
|
private static ValueEval chooseSingleElementFromRef(RefEval ref) {
|
||||||
return ref.getInnerValueEval( ref.getFirstSheetIndex() );
|
return ref.getInnerValueEval( ref.getFirstSheetIndex() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies some conversion rules if the supplied value is not already an integer.<br/>
|
* Applies some conversion rules if the supplied value is not already an integer.<br/>
|
||||||
* Value is first coerced to a <tt>double</tt> ( See <tt>coerceValueToDouble()</tt> ).
|
* Value is first coerced to a <tt>double</tt> ( See <tt>coerceValueToDouble()</tt> ).
|
||||||
* Note - <tt>BlankEval</tt> is converted to <code>0</code>.<p/>
|
* Note - <tt>BlankEval</tt> is converted to <code>0</code>.<p/>
|
||||||
*
|
*
|
||||||
* Excel typically converts doubles to integers by truncating toward negative infinity.<br/>
|
* Excel typically converts doubles to integers by truncating toward negative infinity.<br/>
|
||||||
* The equivalent java code is:<br/>
|
* The equivalent java code is:<br/>
|
||||||
* <code>return (int)Math.floor(d);</code><br/>
|
* <code>return (int)Math.floor(d);</code><br/>
|
||||||
* <b>not</b>:<br/>
|
* <b>not</b>:<br/>
|
||||||
* <code>return (int)d; // wrong - rounds toward zero</code>
|
* <code>return (int)d; // wrong - rounds toward zero</code>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static int coerceValueToInt(ValueEval ev) throws EvaluationException {
|
public static int coerceValueToInt(ValueEval ev) throws EvaluationException {
|
||||||
if (ev == BlankEval.instance) {
|
if (ev == BlankEval.instance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
double d = coerceValueToDouble(ev);
|
double d = coerceValueToDouble(ev);
|
||||||
// Note - the standard java type conversion from double to int truncates toward zero.
|
// Note - the standard java type conversion from double to int truncates toward zero.
|
||||||
// but Math.floor() truncates toward negative infinity
|
// but Math.floor() truncates toward negative infinity
|
||||||
return (int)Math.floor(d);
|
return (int)Math.floor(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies some conversion rules if the supplied value is not already a number.
|
* Applies some conversion rules if the supplied value is not already a number.
|
||||||
* Note - <tt>BlankEval</tt> is converted to {@link NumberEval#ZERO}.
|
* Note - <tt>BlankEval</tt> is converted to {@link NumberEval#ZERO}.
|
||||||
* @param ev must be a {@link NumberEval}, {@link StringEval}, {@link BoolEval} or
|
* @param ev must be a {@link NumberEval}, {@link StringEval}, {@link BoolEval} or
|
||||||
* {@link BlankEval}
|
* {@link BlankEval}
|
||||||
* @return actual, parsed or interpreted double value (respectively).
|
* @return actual, parsed or interpreted double value (respectively).
|
||||||
* @throws EvaluationException(#VALUE!) only if a StringEval is supplied and cannot be parsed
|
* @throws EvaluationException(#VALUE!) only if a StringEval is supplied and cannot be parsed
|
||||||
* as a double (See <tt>parseDouble()</tt> for allowable formats).
|
* as a double (See <tt>parseDouble()</tt> for allowable formats).
|
||||||
* @throws RuntimeException if the supplied parameter is not {@link NumberEval},
|
* @throws RuntimeException if the supplied parameter is not {@link NumberEval},
|
||||||
* {@link StringEval}, {@link BoolEval} or {@link BlankEval}
|
* {@link StringEval}, {@link BoolEval} or {@link BlankEval}
|
||||||
*/
|
*/
|
||||||
public static double coerceValueToDouble(ValueEval ev) throws EvaluationException {
|
public static double coerceValueToDouble(ValueEval ev) throws EvaluationException {
|
||||||
|
|
||||||
if (ev == BlankEval.instance) {
|
if (ev == BlankEval.instance) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
if (ev instanceof NumericValueEval) {
|
if (ev instanceof NumericValueEval) {
|
||||||
// this also handles booleans
|
// this also handles booleans
|
||||||
return ((NumericValueEval)ev).getNumberValue();
|
return ((NumericValueEval)ev).getNumberValue();
|
||||||
}
|
}
|
||||||
if (ev instanceof StringEval) {
|
if (ev instanceof StringEval) {
|
||||||
Double dd = parseDouble(((StringEval) ev).getStringValue());
|
Double dd = parseDouble(((StringEval) ev).getStringValue());
|
||||||
if (dd == null) {
|
if (dd == null) {
|
||||||
throw EvaluationException.invalidValue();
|
throw EvaluationException.invalidValue();
|
||||||
}
|
}
|
||||||
return dd.doubleValue();
|
return dd.doubleValue();
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Unexpected arg eval type (" + ev.getClass().getName() + ")");
|
throw new RuntimeException("Unexpected arg eval type (" + ev.getClass().getName() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string to a double using standard rules that Excel would use.<br/>
|
* Converts a string to a double using standard rules that Excel would use.<br/>
|
||||||
* Tolerates leading and trailing spaces, <p/>
|
* Tolerates leading and trailing spaces, <p/>
|
||||||
*
|
*
|
||||||
* Doesn't support currency prefixes, commas, percentage signs or arithmetic operations strings.
|
* Doesn't support currency prefixes, commas, percentage signs or arithmetic operations strings.
|
||||||
*
|
*
|
||||||
* Some examples:<br/>
|
* Some examples:<br/>
|
||||||
* " 123 " -> 123.0<br/>
|
* " 123 " -> 123.0<br/>
|
||||||
* ".123" -> 0.123<br/>
|
* ".123" -> 0.123<br/>
|
||||||
* "1E4" -> 1000<br/>
|
* "1E4" -> 1000<br/>
|
||||||
* "-123" -> -123.0<br/>
|
* "-123" -> -123.0<br/>
|
||||||
* These not supported yet:<br/>
|
* These not supported yet:<br/>
|
||||||
* " $ 1,000.00 " -> 1000.0<br/>
|
* " $ 1,000.00 " -> 1000.0<br/>
|
||||||
* "$1.25E4" -> 12500.0<br/>
|
* "$1.25E4" -> 12500.0<br/>
|
||||||
* "5**2" -> 500<br/>
|
* "5**2" -> 500<br/>
|
||||||
* "250%" -> 2.5<br/>
|
* "250%" -> 2.5<br/>
|
||||||
*
|
*
|
||||||
* @return <code>null</code> if the specified text cannot be parsed as a number
|
* @return <code>null</code> if the specified text cannot be parsed as a number
|
||||||
*/
|
*/
|
||||||
public static Double parseDouble(String pText) {
|
public static Double parseDouble(String pText) {
|
||||||
|
|
||||||
if (Pattern.matches(fpRegex, pText))
|
if (Pattern.matches(fpRegex, pText))
|
||||||
try {
|
try {
|
||||||
return Double.parseDouble(pText);
|
return Double.parseDouble(pText);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ve must be a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt>, or <tt>BlankEval</tt>
|
* @param ve must be a <tt>NumberEval</tt>, <tt>StringEval</tt>, <tt>BoolEval</tt>, or <tt>BlankEval</tt>
|
||||||
* @return the converted string value. never <code>null</code>
|
* @return the converted string value. never <code>null</code>
|
||||||
*/
|
*/
|
||||||
public static String coerceValueToString(ValueEval ve) {
|
public static String coerceValueToString(ValueEval ve) {
|
||||||
if (ve instanceof StringValueEval) {
|
if (ve instanceof StringValueEval) {
|
||||||
StringValueEval sve = (StringValueEval) ve;
|
StringValueEval sve = (StringValueEval) ve;
|
||||||
return sve.getStringValue();
|
return sve.getStringValue();
|
||||||
}
|
}
|
||||||
if (ve == BlankEval.instance) {
|
if (ve == BlankEval.instance) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Unexpected eval class (" + ve.getClass().getName() + ")");
|
throw new IllegalArgumentException("Unexpected eval class (" + ve.getClass().getName() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return <code>null</code> to represent blank values
|
* @return <code>null</code> to represent blank values
|
||||||
* @throws EvaluationException if ve is an ErrorEval, or if a string value cannot be converted
|
* @throws EvaluationException if ve is an ErrorEval, or if a string value cannot be converted
|
||||||
*/
|
*/
|
||||||
public static Boolean coerceValueToBoolean(ValueEval ve, boolean stringsAreBlanks) throws EvaluationException {
|
public static Boolean coerceValueToBoolean(ValueEval ve, boolean stringsAreBlanks) throws EvaluationException {
|
||||||
|
|
||||||
if (ve == null || ve == BlankEval.instance) {
|
if (ve == null || ve == BlankEval.instance) {
|
||||||
// TODO - remove 've == null' condition once AreaEval is fixed
|
// TODO - remove 've == null' condition once AreaEval is fixed
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (ve instanceof BoolEval) {
|
if (ve instanceof BoolEval) {
|
||||||
return Boolean.valueOf(((BoolEval) ve).getBooleanValue());
|
return Boolean.valueOf(((BoolEval) ve).getBooleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ve == BlankEval.instance) {
|
if (ve == BlankEval.instance) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ve instanceof StringEval) {
|
if (ve instanceof StringEval) {
|
||||||
if (stringsAreBlanks) {
|
if (stringsAreBlanks) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String str = ((StringEval) ve).getStringValue();
|
String str = ((StringEval) ve).getStringValue();
|
||||||
if (str.equalsIgnoreCase("true")) {
|
if (str.equalsIgnoreCase("true")) {
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
if (str.equalsIgnoreCase("false")) {
|
if (str.equalsIgnoreCase("false")) {
|
||||||
return Boolean.FALSE;
|
return Boolean.FALSE;
|
||||||
}
|
}
|
||||||
// else - string cannot be converted to boolean
|
// else - string cannot be converted to boolean
|
||||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ve instanceof NumericValueEval) {
|
if (ve instanceof NumericValueEval) {
|
||||||
NumericValueEval ne = (NumericValueEval) ve;
|
NumericValueEval ne = (NumericValueEval) ve;
|
||||||
double d = ne.getNumberValue();
|
double d = ne.getNumberValue();
|
||||||
if (Double.isNaN(d)) {
|
if (Double.isNaN(d)) {
|
||||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
}
|
}
|
||||||
return Boolean.valueOf(d != 0);
|
return Boolean.valueOf(d != 0);
|
||||||
}
|
}
|
||||||
if (ve instanceof ErrorEval) {
|
if (ve instanceof ErrorEval) {
|
||||||
throw new EvaluationException((ErrorEval) ve);
|
throw new EvaluationException((ErrorEval) ve);
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Unexpected eval (" + ve.getClass().getName() + ")");
|
throw new RuntimeException("Unexpected eval (" + ve.getClass().getName() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user