src/core/net/sf/basedb/util/jep/Jep.java

Code
Comments
Other
Rev Date Author Line
1581 09 Nov 05 nicklas 1 /*
1581 09 Nov 05 nicklas 2   $Id$
1581 09 Nov 05 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2005 Nicklas Nordborg
4889 06 Apr 09 nicklas 5   Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg
3675 16 Aug 07 jari 6   Copyright (C) 2007 Nicklas Nordborg
1581 09 Nov 05 nicklas 7
2304 22 May 06 jari 8   This file is part of BASE - BioArray Software Environment.
2304 22 May 06 jari 9   Available at http://base.thep.lu.se/
1581 09 Nov 05 nicklas 10
1581 09 Nov 05 nicklas 11   BASE is free software; you can redistribute it and/or
1581 09 Nov 05 nicklas 12   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 13   as published by the Free Software Foundation; either version 3
1581 09 Nov 05 nicklas 14   of the License, or (at your option) any later version.
1581 09 Nov 05 nicklas 15
1581 09 Nov 05 nicklas 16   BASE is distributed in the hope that it will be useful,
1581 09 Nov 05 nicklas 17   but WITHOUT ANY WARRANTY; without even the implied warranty of
1581 09 Nov 05 nicklas 18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1581 09 Nov 05 nicklas 19   GNU General Public License for more details.
1581 09 Nov 05 nicklas 20
1581 09 Nov 05 nicklas 21   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 22   along with BASE. If not, see <http://www.gnu.org/licenses/>.
1581 09 Nov 05 nicklas 23 */
1581 09 Nov 05 nicklas 24 package net.sf.basedb.util.jep;
1581 09 Nov 05 nicklas 25
3604 26 Jul 07 nicklas 26 import java.util.Collection;
2655 22 Sep 06 nicklas 27 import java.util.Vector;
2655 22 Sep 06 nicklas 28
1581 09 Nov 05 nicklas 29 import net.sf.basedb.core.BaseException;
2086 17 Mar 06 nicklas 30 import net.sf.basedb.core.VirtualColumn;
1581 09 Nov 05 nicklas 31 import net.sf.basedb.core.query.Expressions;
1581 09 Nov 05 nicklas 32 import net.sf.basedb.core.query.Expression;
1581 09 Nov 05 nicklas 33 import net.sf.basedb.core.query.Dynamic;
1581 09 Nov 05 nicklas 34 import net.sf.basedb.core.query.Restrictions;
1581 09 Nov 05 nicklas 35 import net.sf.basedb.core.query.Restriction;
2292 19 May 06 nicklas 36 import net.sf.basedb.util.Enumeration;
3604 26 Jul 07 nicklas 37 import net.sf.basedb.util.jep.convert.ConverterFactory;
3604 26 Jul 07 nicklas 38 import net.sf.basedb.util.jep.convert.JepConversionFunction;
1581 09 Nov 05 nicklas 39
1581 09 Nov 05 nicklas 40 import org.nfunk.jep.JEP;
1581 09 Nov 05 nicklas 41 import org.nfunk.jep.Node;
1581 09 Nov 05 nicklas 42 import org.nfunk.jep.ASTVarNode;
1581 09 Nov 05 nicklas 43 import org.nfunk.jep.ASTConstant;
1581 09 Nov 05 nicklas 44
1581 09 Nov 05 nicklas 45 /**
1581 09 Nov 05 nicklas 46   Utility class for parsing mathematical expressions. This class uses
1581 09 Nov 05 nicklas 47   the Java Mathematical Expression Parser package from Singular Systems to
1581 09 Nov 05 nicklas 48   parse mathematical expressions.
1581 09 Nov 05 nicklas 49   <p>
1581 09 Nov 05 nicklas 50   Create a new {@link JEP} expression with the {@link #newJep(String, JepFunction[])}
1581 09 Nov 05 nicklas 51   method. If the expression contains variables set values for those with the
1581 09 Nov 05 nicklas 52   {@link JEP#setVarValue(String, Object)} method. Then, evaluate the expression
1581 09 Nov 05 nicklas 53   using the {@link JEP#getValue()} method.
1581 09 Nov 05 nicklas 54   <p>
1581 09 Nov 05 nicklas 55   You can also convert the expression to a Query API {@link Expression}
1581 09 Nov 05 nicklas 56   object with the {@link #jepToExpression(JEP)} method. The conversion
1581 09 Nov 05 nicklas 57   doesn't support all methods since the Query API doesn't have support for
1581 09 Nov 05 nicklas 58   them.
1581 09 Nov 05 nicklas 59   <p>
1581 09 Nov 05 nicklas 60   See the <a href="http://www.singularsys.com/jep/">JEP homepage</a> for more
1581 09 Nov 05 nicklas 61   information about JEP and all supported functions/operators. 
1581 09 Nov 05 nicklas 62   See {@link #jepToExpression(JEP)} and {@link #jepToRestriction(JEP)} 
1581 09 Nov 05 nicklas 63   for functions/operators supported by the conversion methods.
1581 09 Nov 05 nicklas 64
1581 09 Nov 05 nicklas 65   @author Nicklas
1581 09 Nov 05 nicklas 66   @version 2.0
1581 09 Nov 05 nicklas 67   @base.modified $Date$
1581 09 Nov 05 nicklas 68   @see <a href="http://www.singularsys.com/jep/">Java Mathematical Expression Parser package</a>
1581 09 Nov 05 nicklas 69 */
1581 09 Nov 05 nicklas 70 public class Jep
1581 09 Nov 05 nicklas 71 {
1581 09 Nov 05 nicklas 72
5384 13 Aug 10 nicklas 73   private static volatile Enumeration<String, String> functions;
5384 13 Aug 10 nicklas 74   private static volatile Enumeration<String, String> operators;
2292 19 May 06 nicklas 75   
1581 09 Nov 05 nicklas 76   /**
1581 09 Nov 05 nicklas 77     Create a new JEP expression. Evaluate the expression using
1581 09 Nov 05 nicklas 78     the {@link JEP#getValue()} method. Set values for variables
1581 09 Nov 05 nicklas 79     with the {@link JEP#setVarValue(String, Object)}. 
1581 09 Nov 05 nicklas 80     
1581 09 Nov 05 nicklas 81     @param formula The expression to parse
1581 09 Nov 05 nicklas 82     @param functions Extra functions that are required to parse the
1581 09 Nov 05 nicklas 83       expression
1581 09 Nov 05 nicklas 84     @return A <code>JEP</code> object
1581 09 Nov 05 nicklas 85     @throws BaseException If the expression couldn't be parsed
1581 09 Nov 05 nicklas 86   */
1581 09 Nov 05 nicklas 87   public static JEP newJep(String formula, JepFunction... functions)
1581 09 Nov 05 nicklas 88     throws BaseException
1581 09 Nov 05 nicklas 89   {
1581 09 Nov 05 nicklas 90     formula = formula.replace("'", "\"");
5319 20 Apr 10 nicklas 91     JEP jep = new FunctionSafeJep();
1581 09 Nov 05 nicklas 92     jep.setAllowUndeclared(true);
1581 09 Nov 05 nicklas 93     jep.addStandardFunctions();
2086 17 Mar 06 nicklas 94     addFunctions(jep, Log2Function.getInstance());
2086 17 Mar 06 nicklas 95     if (functions != null) addFunctions(jep, functions);
1581 09 Nov 05 nicklas 96     jep.parseExpression(formula);
1581 09 Nov 05 nicklas 97     if (jep.hasError())
1581 09 Nov 05 nicklas 98     {
5319 20 Apr 10 nicklas 99       throw new BaseException(jep.getErrorInfo().replace("\n", " ") + "in formula " + formula);
1581 09 Nov 05 nicklas 100     }
1581 09 Nov 05 nicklas 101     return jep;
1581 09 Nov 05 nicklas 102   }
1581 09 Nov 05 nicklas 103   
2086 17 Mar 06 nicklas 104   private static void addFunctions(JEP jep, JepFunction... functions)
2086 17 Mar 06 nicklas 105   {
2086 17 Mar 06 nicklas 106     for (JepFunction function : functions)
2086 17 Mar 06 nicklas 107     {
2086 17 Mar 06 nicklas 108       if (function != null) jep.addFunction(function.getFunctionName(), function);
2086 17 Mar 06 nicklas 109     }
2086 17 Mar 06 nicklas 110   }
2086 17 Mar 06 nicklas 111   
1581 09 Nov 05 nicklas 112   /**
3604 26 Jul 07 nicklas 113     Get a list of built-in functions supported by the {@link #jepToExpression(JEP)}
3604 26 Jul 07 nicklas 114     converter. More functions can be registered when creating the JEP
3604 26 Jul 07 nicklas 115     expression (see {@link #newJep(String, JepFunction[])}).
3604 26 Jul 07 nicklas 116     
2292 19 May 06 nicklas 117     @return An enumeration with the name of the function in the key 
2292 19 May 06 nicklas 118       and a description in the value part
2292 19 May 06 nicklas 119   */
2292 19 May 06 nicklas 120   public static Enumeration<String, String> getFunctions()
2292 19 May 06 nicklas 121   {
2292 19 May 06 nicklas 122     if (functions == null)
2292 19 May 06 nicklas 123     {
5384 13 Aug 10 nicklas 124       synchronized (Jep.class)
3604 26 Jul 07 nicklas 125       {
5384 13 Aug 10 nicklas 126         if (functions == null)
3604 26 Jul 07 nicklas 127         {
5384 13 Aug 10 nicklas 128           functions = new Enumeration<String, String>();
5384 13 Aug 10 nicklas 129           // Built-in converters
5384 13 Aug 10 nicklas 130           Collection<JepConversionFunction<?>> converters = ConverterFactory.getConverters();
6875 20 Apr 15 nicklas 131           for (JepConversionFunction<?> converter : converters)
5384 13 Aug 10 nicklas 132           {
5384 13 Aug 10 nicklas 133             if (converter.isFunction())
5384 13 Aug 10 nicklas 134             {
5384 13 Aug 10 nicklas 135               functions.add(converter.getName(), converter.getDescription());
5384 13 Aug 10 nicklas 136             }
5384 13 Aug 10 nicklas 137           }
5689 11 Aug 11 nicklas 138           // Other standard functions that we always add. See newJep() method
5384 13 Aug 10 nicklas 139           functions.add("log2", "2-based logarithm");
5384 13 Aug 10 nicklas 140           functions.sortKeys();
5384 13 Aug 10 nicklas 141           functions.lock();
3604 26 Jul 07 nicklas 142         }
3604 26 Jul 07 nicklas 143       }
2292 19 May 06 nicklas 144     }
2292 19 May 06 nicklas 145     return functions;
2292 19 May 06 nicklas 146   }
2292 19 May 06 nicklas 147   
2292 19 May 06 nicklas 148   /**
3604 26 Jul 07 nicklas 149     Get a list of built-in operators supported by the {@link #jepToExpression(JEP)}
3604 26 Jul 07 nicklas 150     and {@link #jepToRestriction(JEP)} converter. It is not possible to
3604 26 Jul 07 nicklas 151     register more operators.
3604 26 Jul 07 nicklas 152     
3604 26 Jul 07 nicklas 153     @return An enumeration with the symbol of the operator in the key 
3604 26 Jul 07 nicklas 154       and a description in the value part
3604 26 Jul 07 nicklas 155     @since 2.4
3604 26 Jul 07 nicklas 156   */
3604 26 Jul 07 nicklas 157   public static Enumeration<String, String> getOperators()
3604 26 Jul 07 nicklas 158   {
3604 26 Jul 07 nicklas 159     if (operators == null)
3604 26 Jul 07 nicklas 160     {
5384 13 Aug 10 nicklas 161       synchronized (Jep.class)
3604 26 Jul 07 nicklas 162       {
5384 13 Aug 10 nicklas 163         if (operators == null)
3604 26 Jul 07 nicklas 164         {
5384 13 Aug 10 nicklas 165           operators = new Enumeration<String, String>();
5384 13 Aug 10 nicklas 166           // Built-in converters
5384 13 Aug 10 nicklas 167           Collection<JepConversionFunction<?>> converters = ConverterFactory.getConverters();
6875 20 Apr 15 nicklas 168           for (JepConversionFunction<?> converter : converters)
5384 13 Aug 10 nicklas 169           {
5384 13 Aug 10 nicklas 170             if (converter.isOperator())
5384 13 Aug 10 nicklas 171             {
5384 13 Aug 10 nicklas 172               operators.add(converter.getName(), converter.getDescription());
5384 13 Aug 10 nicklas 173             }
5384 13 Aug 10 nicklas 174           }
5384 13 Aug 10 nicklas 175           operators.sortKeys();
5384 13 Aug 10 nicklas 176           operators.lock();
3604 26 Jul 07 nicklas 177         }
3604 26 Jul 07 nicklas 178       }
3604 26 Jul 07 nicklas 179     }
3604 26 Jul 07 nicklas 180     return operators;
3604 26 Jul 07 nicklas 181   }
3604 26 Jul 07 nicklas 182
3604 26 Jul 07 nicklas 183   
3604 26 Jul 07 nicklas 184   /**
1581 09 Nov 05 nicklas 185     Convert a JEP expression to a Query API {@link Expression}. The Query API
1581 09 Nov 05 nicklas 186     only supports a subset of the functions/operators that JEP supports.
2292 19 May 06 nicklas 187     Supported operators are:
1581 09 Nov 05 nicklas 188
1581 09 Nov 05 nicklas 189     <pre class="code">
1581 09 Nov 05 nicklas 190 +      {@link Expressions#add(Expression, Expression)}
1581 09 Nov 05 nicklas 191 -      {@link Expressions#subtract(Expression, Expression)}
1581 09 Nov 05 nicklas 192 *      {@link Expressions#multiply(Expression, Expression)}
1581 09 Nov 05 nicklas 193 /      {@link Expressions#divide(Expression, Expression)}
1581 09 Nov 05 nicklas 194 -      {@link Expressions#negate(Expression)}
2292 19 May 06 nicklas 195 log    {@link Expressions#log10(Expression)}
2086 17 Mar 06 nicklas 196 log2   {@link Expressions#log2(Expression)}
1581 09 Nov 05 nicklas 197 ln     {@link Expressions#ln(Expression)}
2302 22 May 06 nicklas 198 sqrt   {@link Expressions#sqrt(Expression)}
2292 19 May 06 nicklas 199 abs    {@link Expressions#abs(Expression)}
2292 19 May 06 nicklas 200 exp    {@link Expressions#exp(Expression)}
1581 09 Nov 05 nicklas 201 raw    {@link Dynamic#rawData(String)} *
2086 17 Mar 06 nicklas 202 ch     {@link Dynamic#column(VirtualColumn)} *
4912 29 Apr 09 nicklas 203 rawCh  {@link Dynamic#column(VirtualColumn)} *
1581 09 Nov 05 nicklas 204 <i>number</i> {@link Expressions#integer(int)} or
1581 09 Nov 05 nicklas 205        {@link Expressions#aFloat(float)}
1581 09 Nov 05 nicklas 206 <i>string</i> {@link Expressions#parameter(String, Object)}
3456 06 Jun 07 nicklas 207 <i>variable</i> {@link Expressions#parameter(String)} **
1581 09 Nov 05 nicklas 208 </pre>
3456 06 Jun 07 nicklas 209     * = This is a optional function that must be registered when creating the 
3456 06 Jun 07 nicklas 210     JEP object.
3456 06 Jun 07 nicklas 211     <br>
3456 06 Jun 07 nicklas 212     ** = The NULL string is converted to a NULL value
1581 09 Nov 05 nicklas 213     
1581 09 Nov 05 nicklas 214     @param jep The JEP object
1581 09 Nov 05 nicklas 215     @return An <code>Expression</code> object
1581 09 Nov 05 nicklas 216     @throws BaseException If the JEP expression can't be converted
1584 10 Nov 05 nicklas 217     @see #newJep(String, JepFunction[])
2292 19 May 06 nicklas 218     @see #getFunctions()
1581 09 Nov 05 nicklas 219   */
1581 09 Nov 05 nicklas 220   public static Expression jepToExpression(JEP jep)
1581 09 Nov 05 nicklas 221     throws BaseException
1581 09 Nov 05 nicklas 222   {
1581 09 Nov 05 nicklas 223     return nodeToExpression(jep.getTopNode());
1581 09 Nov 05 nicklas 224   }
1581 09 Nov 05 nicklas 225   
1581 09 Nov 05 nicklas 226   /**
1581 09 Nov 05 nicklas 227     Convert JEP expression to a Query API {@link Expression}. This method
1581 09 Nov 05 nicklas 228     is equivalent to: <code>jepToExpression(newJep(formula, functions))</code>.
1581 09 Nov 05 nicklas 229     @see #jepToExpression(JEP)
1581 09 Nov 05 nicklas 230   */
1581 09 Nov 05 nicklas 231   public static Expression formulaToExpression(String formula, JepFunction... functions)
1581 09 Nov 05 nicklas 232     throws BaseException
1581 09 Nov 05 nicklas 233   {
1581 09 Nov 05 nicklas 234     return jepToExpression(newJep(formula, functions));
1581 09 Nov 05 nicklas 235   }
1581 09 Nov 05 nicklas 236   
1581 09 Nov 05 nicklas 237   /**
1581 09 Nov 05 nicklas 238     Convert a JEP expression to a Query API {@link Restriction}. The
1581 09 Nov 05 nicklas 239     Query API only supports a subset of the functions/operators that
1581 09 Nov 05 nicklas 240     JEP supports. 
1581 09 Nov 05 nicklas 241     Supported functions/operators are:
1581 09 Nov 05 nicklas 242     <pre class="code">
1584 10 Nov 05 nicklas 243 ==      {@link Restrictions#eq(Expression, Expression)}
1584 10 Nov 05 nicklas 244 !=      {@link Restrictions#neq(Expression, Expression)}
1584 10 Nov 05 nicklas 245 &gt;       {@link Restrictions#gt(Expression, Expression)}
1584 10 Nov 05 nicklas 246 &gt;=      {@link Restrictions#gteq(Expression, Expression)}
1584 10 Nov 05 nicklas 247 &lt;       {@link Restrictions#lt(Expression, Expression)}
1584 10 Nov 05 nicklas 248 &lt;=      {@link Restrictions#lteq(Expression, Expression)}
6898 12 May 15 nicklas 249 &gt;       {@link Restrictions#gt(Expression, Expression)}
6898 12 May 15 nicklas 250 &amp;&amp;      {@link Restrictions#and(Restriction[])}
1584 10 Nov 05 nicklas 251 ||      {@link Restrictions#or(Restriction[])}
1584 10 Nov 05 nicklas 252 !       {@link Restrictions#not(Restriction)}
1581 09 Nov 05 nicklas 253 </pre>
1581 09 Nov 05 nicklas 254     * = This is a optional function that must be registered when creating the JEP object.
1581 09 Nov 05 nicklas 255     <p>
1581 09 Nov 05 nicklas 256     All operators supported by the {@link #jepToExpression(JEP)} are of
1581 09 Nov 05 nicklas 257     course also supported in the appropriate places.
1581 09 Nov 05 nicklas 258     
1581 09 Nov 05 nicklas 259     @param jep The JEP object
1581 09 Nov 05 nicklas 260     @return A <code>Restriction</code> object
1581 09 Nov 05 nicklas 261     @throws BaseException If the JEP expression can't be converted
1584 10 Nov 05 nicklas 262     @see #newJep(String, JepFunction[])
1581 09 Nov 05 nicklas 263   */
1581 09 Nov 05 nicklas 264   public static Restriction jepToRestriction(JEP jep)
1581 09 Nov 05 nicklas 265     throws BaseException
1581 09 Nov 05 nicklas 266   {
3604 26 Jul 07 nicklas 267     return nodeToRestriction(jep.getTopNode());
1581 09 Nov 05 nicklas 268   }
1581 09 Nov 05 nicklas 269   
1581 09 Nov 05 nicklas 270   /**
1581 09 Nov 05 nicklas 271     Convert JEP expression to a Query API {@link Restriction}. This method
1581 09 Nov 05 nicklas 272     is equivalent to: <code>jepToRestriction(newJep(formula, functions))</code>.
1581 09 Nov 05 nicklas 273     @see #jepToRestriction(JEP)
1581 09 Nov 05 nicklas 274   */
1581 09 Nov 05 nicklas 275   public static Restriction formulaToRestriction(String formula, JepFunction... functions)
1581 09 Nov 05 nicklas 276     throws BaseException
1581 09 Nov 05 nicklas 277   {
1581 09 Nov 05 nicklas 278     return jepToRestriction(newJep(formula, functions));
1581 09 Nov 05 nicklas 279   }
1581 09 Nov 05 nicklas 280
1581 09 Nov 05 nicklas 281   /**
1581 09 Nov 05 nicklas 282     Convert a node with it's children to an expression.
4020 29 Nov 07 martin 283      @param node Node to convert to an expression
4020 29 Nov 07 martin 284      @return A {@link net.sf.basedb.core.query.Expression} object
4020 29 Nov 07 martin 285      @throws BaseException If the JEP function in node not is supported.
1581 09 Nov 05 nicklas 286   */
6875 20 Apr 15 nicklas 287   @SuppressWarnings({ "unchecked", "rawtypes" })
2086 17 Mar 06 nicklas 288   public static Expression nodeToExpression(Node node)
1581 09 Nov 05 nicklas 289     throws BaseException
1581 09 Nov 05 nicklas 290   {
3604 26 Jul 07 nicklas 291     JepConversionFunction converter = ConverterFactory.getConverterByClass(node);
3604 26 Jul 07 nicklas 292     Expression e = null;
3604 26 Jul 07 nicklas 293     if (converter != null)
1581 09 Nov 05 nicklas 294     {
3604 26 Jul 07 nicklas 295       e = converter.toExpression(node);
1581 09 Nov 05 nicklas 296     }
1581 09 Nov 05 nicklas 297     else
1581 09 Nov 05 nicklas 298     {
3604 26 Jul 07 nicklas 299       throw new BaseException("Unsupported JEP function: " + node);
1581 09 Nov 05 nicklas 300     }
3604 26 Jul 07 nicklas 301     return e;
1581 09 Nov 05 nicklas 302   }
1581 09 Nov 05 nicklas 303   
3604 26 Jul 07 nicklas 304   /**
3604 26 Jul 07 nicklas 305     Convert a node with it's children to a restriction.
4020 29 Nov 07 martin 306      @param node JEP node to convert. 
4020 29 Nov 07 martin 307      @return A {@link net.sf.basedb.core.query.Restriction} object
4020 29 Nov 07 martin 308      @throws BaseException If the JEP function in node is not supported by the converter.
3604 26 Jul 07 nicklas 309     @since 2.4
3604 26 Jul 07 nicklas 310   */
6875 20 Apr 15 nicklas 311   @SuppressWarnings({ "unchecked", "rawtypes" })
3604 26 Jul 07 nicklas 312   public static Restriction nodeToRestriction(Node node)
1581 09 Nov 05 nicklas 313     throws BaseException
1581 09 Nov 05 nicklas 314   {
3604 26 Jul 07 nicklas 315     JepConversionFunction converter = ConverterFactory.getConverterByClass(node);
3604 26 Jul 07 nicklas 316     Restriction r = null;
3604 26 Jul 07 nicklas 317     if (converter != null)
1581 09 Nov 05 nicklas 318     {
3604 26 Jul 07 nicklas 319       r = converter.toRestriction(node);
1581 09 Nov 05 nicklas 320     }
1581 09 Nov 05 nicklas 321     else
1581 09 Nov 05 nicklas 322     {
3604 26 Jul 07 nicklas 323       throw new BaseException("Unsupported JEP function: " + node);
1581 09 Nov 05 nicklas 324     }
3604 26 Jul 07 nicklas 325     return r;
1581 09 Nov 05 nicklas 326   }
1581 09 Nov 05 nicklas 327   
1581 09 Nov 05 nicklas 328   /**
1581 09 Nov 05 nicklas 329     Convert a node to a string value. Supported node types are
2669 27 Sep 06 nicklas 330     constants or variables. Constants will be converted to strings with the
2669 27 Sep 06 nicklas 331     toString() method. For variables the name is returned as the string. 
3456 06 Jun 07 nicklas 332     This allows for unquoted strings in expressions. The NULL string
3456 06 Jun 07 nicklas 333     is converted to a NULL value.
4020 29 Nov 07 martin 334      @param node JEP node to convert. 
4020 29 Nov 07 martin 335      @return A String object or null if the node does not have any value.
4020 29 Nov 07 martin 336      @throws BaseException If the node could not be converted in some way.
1581 09 Nov 05 nicklas 337   */
2086 17 Mar 06 nicklas 338   public static String nodeToString(Node node)
1581 09 Nov 05 nicklas 339     throws BaseException
1581 09 Nov 05 nicklas 340   {
1581 09 Nov 05 nicklas 341     if (node instanceof ASTConstant)
1581 09 Nov 05 nicklas 342     {
1581 09 Nov 05 nicklas 343       ASTConstant constNode = (ASTConstant)node;
1581 09 Nov 05 nicklas 344       Object value = constNode.getValue();
2669 27 Sep 06 nicklas 345       return value == null ? null : value.toString();
1581 09 Nov 05 nicklas 346     }
1581 09 Nov 05 nicklas 347     else if (node instanceof ASTVarNode)
1581 09 Nov 05 nicklas 348     {
1581 09 Nov 05 nicklas 349       ASTVarNode varNode = (ASTVarNode)node;
3456 06 Jun 07 nicklas 350       String name = varNode.getName();
3456 06 Jun 07 nicklas 351       if ("NULL".equalsIgnoreCase(name)) name = null;
3456 06 Jun 07 nicklas 352       return name;
1581 09 Nov 05 nicklas 353     }
1581 09 Nov 05 nicklas 354     throw new BaseException("Expected string expression: " + node);
1581 09 Nov 05 nicklas 355   }
2086 17 Mar 06 nicklas 356   
2086 17 Mar 06 nicklas 357   /**
2086 17 Mar 06 nicklas 358     Convert a node to an integer value. Supported node types are
2086 17 Mar 06 nicklas 359     constants.
4020 29 Nov 07 martin 360      @param node JEP node to convert. 
4020 29 Nov 07 martin 361      @return an int object
4020 29 Nov 07 martin 362      @throws BaseException If the node could not be converted.
2086 17 Mar 06 nicklas 363   */
2086 17 Mar 06 nicklas 364   public static int nodeToInt(Node node)
2086 17 Mar 06 nicklas 365     throws BaseException
2086 17 Mar 06 nicklas 366   {
2086 17 Mar 06 nicklas 367     if (node instanceof ASTConstant)
2086 17 Mar 06 nicklas 368     {
2086 17 Mar 06 nicklas 369       ASTConstant constNode = (ASTConstant)node;
2086 17 Mar 06 nicklas 370       Object value = constNode.getValue();
2086 17 Mar 06 nicklas 371       if (value instanceof Number)
2086 17 Mar 06 nicklas 372       {
2086 17 Mar 06 nicklas 373         return ((Number)value).intValue();
2086 17 Mar 06 nicklas 374       }
2086 17 Mar 06 nicklas 375     }
2086 17 Mar 06 nicklas 376     throw new BaseException("Expected integer expression: " + node);
2086 17 Mar 06 nicklas 377   }
2655 22 Sep 06 nicklas 378   
2655 22 Sep 06 nicklas 379   private static java.lang.reflect.Field jepErrorList = null;
2655 22 Sep 06 nicklas 380   static
2655 22 Sep 06 nicklas 381   {
2655 22 Sep 06 nicklas 382     try
2655 22 Sep 06 nicklas 383     {
2655 22 Sep 06 nicklas 384       jepErrorList = JEP.class.getDeclaredField("errorList");
2655 22 Sep 06 nicklas 385       jepErrorList.setAccessible(true);
2655 22 Sep 06 nicklas 386     }
2655 22 Sep 06 nicklas 387     catch (Throwable t)
2655 22 Sep 06 nicklas 388     {}
2655 22 Sep 06 nicklas 389   }
2655 22 Sep 06 nicklas 390   
2655 22 Sep 06 nicklas 391   /**
2655 22 Sep 06 nicklas 392     This is a workaround for a bug in the JEP error handling. Before calling
2655 22 Sep 06 nicklas 393     {@link JEP#getValueAsObject()} the error list should be cleared.
2655 22 Sep 06 nicklas 394   */
6875 20 Apr 15 nicklas 395   @SuppressWarnings("rawtypes")
2655 22 Sep 06 nicklas 396   public static void clearErrorList(JEP jep)
2655 22 Sep 06 nicklas 397   {
2655 22 Sep 06 nicklas 398     try
2655 22 Sep 06 nicklas 399     {
2655 22 Sep 06 nicklas 400       Vector v = (Vector)jepErrorList.get(jep);
2655 22 Sep 06 nicklas 401       v.clear();
2655 22 Sep 06 nicklas 402     }
2655 22 Sep 06 nicklas 403     catch (Throwable t)
2655 22 Sep 06 nicklas 404     {}
2655 22 Sep 06 nicklas 405   }
2655 22 Sep 06 nicklas 406   
1581 09 Nov 05 nicklas 407
1581 09 Nov 05 nicklas 408 }