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

Code
Comments
Other
Rev Date Author Line
2664 26 Sep 06 nicklas 1 /*
2664 26 Sep 06 nicklas 2   $Id$
2664 26 Sep 06 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2006 Nicklas Nordborg
2664 26 Sep 06 nicklas 5
2664 26 Sep 06 nicklas 6   This file is part of BASE - BioArray Software Environment.
2664 26 Sep 06 nicklas 7   Available at http://base.thep.lu.se/
2664 26 Sep 06 nicklas 8
2664 26 Sep 06 nicklas 9   BASE is free software; you can redistribute it and/or
2664 26 Sep 06 nicklas 10   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 11   as published by the Free Software Foundation; either version 3
2664 26 Sep 06 nicklas 12   of the License, or (at your option) any later version.
2664 26 Sep 06 nicklas 13
2664 26 Sep 06 nicklas 14   BASE is distributed in the hope that it will be useful,
2664 26 Sep 06 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
2664 26 Sep 06 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2664 26 Sep 06 nicklas 17   GNU General Public License for more details.
2664 26 Sep 06 nicklas 18
2664 26 Sep 06 nicklas 19   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
2664 26 Sep 06 nicklas 21 */
2664 26 Sep 06 nicklas 22 package net.sf.basedb.util.jep;
2664 26 Sep 06 nicklas 23
2664 26 Sep 06 nicklas 24 import net.sf.basedb.core.BaseException;
2666 26 Sep 06 nicklas 25 import net.sf.basedb.core.BioAssaySet;
5319 20 Apr 10 nicklas 26 import net.sf.basedb.core.DynamicQuery;
2664 26 Sep 06 nicklas 27 import net.sf.basedb.core.ExtraValue;
2664 26 Sep 06 nicklas 28 import net.sf.basedb.core.DbControl;
2666 26 Sep 06 nicklas 29 import net.sf.basedb.core.ExtraValueType;
2664 26 Sep 06 nicklas 30 import net.sf.basedb.core.query.Dynamic;
2664 26 Sep 06 nicklas 31 import net.sf.basedb.core.query.Expression;
2664 26 Sep 06 nicklas 32 import net.sf.basedb.core.query.SqlResult;
2981 30 Nov 06 nicklas 33 import net.sf.basedb.util.BioAssaySetUtil;
2666 26 Sep 06 nicklas 34 import net.sf.basedb.util.Values;
2664 26 Sep 06 nicklas 35
2664 26 Sep 06 nicklas 36 import java.sql.SQLException;
2664 26 Sep 06 nicklas 37 import java.util.Map;
2664 26 Sep 06 nicklas 38 import java.util.Stack;
2664 26 Sep 06 nicklas 39
2664 26 Sep 06 nicklas 40 import org.nfunk.jep.Node;
2664 26 Sep 06 nicklas 41 import org.nfunk.jep.ParseException;
2664 26 Sep 06 nicklas 42
2664 26 Sep 06 nicklas 43
2664 26 Sep 06 nicklas 44 /**
2664 26 Sep 06 nicklas 45   A JEP function class that adds a <code>xtra(int)</code> function to a 
2664 26 Sep 06 nicklas 46   JEP expression parser. The function will look up the value of the extra value
2664 26 Sep 06 nicklas 47   with the given ID. For example: <code>xtra(1)</code>
2664 26 Sep 06 nicklas 48   <p>
2664 26 Sep 06 nicklas 49   To be able to use this function it must be registered with the JEP
2664 26 Sep 06 nicklas 50   parser.
2664 26 Sep 06 nicklas 51   
2664 26 Sep 06 nicklas 52   @author Nicklas
2664 26 Sep 06 nicklas 53   @version 2.0
2664 26 Sep 06 nicklas 54   @base.modified $Date$
2664 26 Sep 06 nicklas 55   @see Jep
5319 20 Apr 10 nicklas 56   @see BioAssaySetUtil#createJepExpression(DbControl, String, DynamicQuery)
2664 26 Sep 06 nicklas 57 */
2664 26 Sep 06 nicklas 58 public class ExtraValueFunction
2664 26 Sep 06 nicklas 59   implements JepExpressionFunction
2664 26 Sep 06 nicklas 60 {
2664 26 Sep 06 nicklas 61   private final DbControl dc;
2664 26 Sep 06 nicklas 62   private final Map<Integer, Integer> extraToIndex;
2666 26 Sep 06 nicklas 63   private final BioAssaySet bas;
2664 26 Sep 06 nicklas 64   private int numParameters;
2664 26 Sep 06 nicklas 65   private SqlResult result;
2664 26 Sep 06 nicklas 66
2664 26 Sep 06 nicklas 67   /**
2664 26 Sep 06 nicklas 68     Create a new instance of this function. The new instance cannot be used
2664 26 Sep 06 nicklas 69     to dynamically evaluate expressions. It should only be used for converting
2664 26 Sep 06 nicklas 70     JEP formulas to {@link Expression}:s.
4034 05 Dec 07 martin 71      @param dc DbControl to use when accessing the database 
4034 05 Dec 07 martin 72      @param bas Bioassay set for this extra value function. 
2664 26 Sep 06 nicklas 73     @see Jep#formulaToExpression(String, JepFunction[])
2664 26 Sep 06 nicklas 74   */
2669 27 Sep 06 nicklas 75   public ExtraValueFunction(DbControl dc, BioAssaySet bas)
2664 26 Sep 06 nicklas 76   {
2664 26 Sep 06 nicklas 77     this.dc = dc;
2664 26 Sep 06 nicklas 78     this.extraToIndex = null;
2666 26 Sep 06 nicklas 79     this.bas = bas;
2664 26 Sep 06 nicklas 80   }
2664 26 Sep 06 nicklas 81   /**
2664 26 Sep 06 nicklas 82     Create a new instance of this function which can be used
2664 26 Sep 06 nicklas 83     to dynamically evaluate expressions.
4034 05 Dec 07 martin 84      @param dc DbControl to use when accessing the database 
2664 26 Sep 06 nicklas 85     @param extraToIndex An map from extra value ID to column indexes in
2664 26 Sep 06 nicklas 86       the SqlResult
2664 26 Sep 06 nicklas 87     @see #setSqlResult(SqlResult)
2664 26 Sep 06 nicklas 88   */
2664 26 Sep 06 nicklas 89   public ExtraValueFunction(DbControl dc, Map<Integer, Integer> extraToIndex)
2664 26 Sep 06 nicklas 90   {
2664 26 Sep 06 nicklas 91     this.dc = dc;
2664 26 Sep 06 nicklas 92     this.extraToIndex = extraToIndex;
2666 26 Sep 06 nicklas 93     this.bas = null;
2664 26 Sep 06 nicklas 94   }  
2664 26 Sep 06 nicklas 95   /*
2664 26 Sep 06 nicklas 96     From the JepFunction interface
2664 26 Sep 06 nicklas 97     -------------------------------------------
2664 26 Sep 06 nicklas 98   */
2664 26 Sep 06 nicklas 99   /**
2664 26 Sep 06 nicklas 100     @return The string "xtra"
2664 26 Sep 06 nicklas 101   */
6127 14 Sep 12 nicklas 102   @Override
2664 26 Sep 06 nicklas 103   public String getFunctionName()
2664 26 Sep 06 nicklas 104   {
2664 26 Sep 06 nicklas 105     return "xtra";
2664 26 Sep 06 nicklas 106   }
2664 26 Sep 06 nicklas 107   // -------------------------------------------
2664 26 Sep 06 nicklas 108   /*
2664 26 Sep 06 nicklas 109     From the JepExpressionFunction interface
2664 26 Sep 06 nicklas 110     -------------------------------------------
2664 26 Sep 06 nicklas 111   */
2664 26 Sep 06 nicklas 112   /**
2664 26 Sep 06 nicklas 113     Use the {@link Dynamic#extraValue(ExtraValue)} method to create an
2664 26 Sep 06 nicklas 114     expression referencing an extra value.
2664 26 Sep 06 nicklas 115   */
6127 14 Sep 12 nicklas 116   @Override
2664 26 Sep 06 nicklas 117   public Expression toExpression(Node node)
2664 26 Sep 06 nicklas 118   {
2664 26 Sep 06 nicklas 119     int numChildren = node.jjtGetNumChildren();
2664 26 Sep 06 nicklas 120     if (numChildren != 1)
2664 26 Sep 06 nicklas 121     {
2664 26 Sep 06 nicklas 122       throw new BaseException("Invalid number of expressions for 'xtra' function: " + numChildren);
2664 26 Sep 06 nicklas 123     }
2666 26 Sep 06 nicklas 124     // First try to load by external id
2666 26 Sep 06 nicklas 125     String arg = Jep.nodeToString(node.jjtGetChild(0));
2669 27 Sep 06 nicklas 126     int extraValueId = Values.getInt(arg, -1);
2669 27 Sep 06 nicklas 127     ExtraValueType xType = extraValueId == -1 ? ExtraValueType.getByExternalId(dc, arg) : null;
2669 27 Sep 06 nicklas 128     ExtraValue xv = xType != null ? bas.getExtraValue(xType) : ExtraValue.getById(dc, extraValueId);
2664 26 Sep 06 nicklas 129     return Dynamic.extraValue(xv);
2664 26 Sep 06 nicklas 130   }
2664 26 Sep 06 nicklas 131   // -------------------------------------------
2664 26 Sep 06 nicklas 132   /*
2664 26 Sep 06 nicklas 133     From the PostfixMathCommandI interface
2664 26 Sep 06 nicklas 134     -------------------------------------------
2664 26 Sep 06 nicklas 135   */
2664 26 Sep 06 nicklas 136   /**
2664 26 Sep 06 nicklas 137     @return Always 1
2664 26 Sep 06 nicklas 138   */
6127 14 Sep 12 nicklas 139   @Override
2664 26 Sep 06 nicklas 140   public int getNumberOfParameters()
2664 26 Sep 06 nicklas 141   {
2664 26 Sep 06 nicklas 142     return 1;
2664 26 Sep 06 nicklas 143   }
6127 14 Sep 12 nicklas 144   @Override
2664 26 Sep 06 nicklas 145   public void setCurNumberOfParameters(int n)
2664 26 Sep 06 nicklas 146   {
2664 26 Sep 06 nicklas 147     this.numParameters = n;
2664 26 Sep 06 nicklas 148   }
6127 14 Sep 12 nicklas 149   @Override
2664 26 Sep 06 nicklas 150   public boolean checkNumberOfParameters(int n)
2664 26 Sep 06 nicklas 151   {
2664 26 Sep 06 nicklas 152     return n == 1;
2664 26 Sep 06 nicklas 153   }
6127 14 Sep 12 nicklas 154   @Override
6875 20 Apr 15 nicklas 155   @SuppressWarnings({"unchecked", "rawtypes"})
2664 26 Sep 06 nicklas 156   public void run(Stack stack)
2664 26 Sep 06 nicklas 157     throws ParseException
2664 26 Sep 06 nicklas 158   {
2664 26 Sep 06 nicklas 159     if (stack == null || stack.empty()) 
2664 26 Sep 06 nicklas 160     {
2664 26 Sep 06 nicklas 161       throw new ParseException("Stack is empty");
2664 26 Sep 06 nicklas 162     }
2664 26 Sep 06 nicklas 163     Object extraId = stack.pop();
2664 26 Sep 06 nicklas 164     if (extraId instanceof Number)
2664 26 Sep 06 nicklas 165     {
2664 26 Sep 06 nicklas 166       stack.push(xtra(((Number)extraId).intValue()));
2664 26 Sep 06 nicklas 167     }
2664 26 Sep 06 nicklas 168     else
2664 26 Sep 06 nicklas 169     {
2664 26 Sep 06 nicklas 170       throw new ParseException("Invalid parameter type: " + extraId + "; expected number");
2664 26 Sep 06 nicklas 171     }
2664 26 Sep 06 nicklas 172   }
2664 26 Sep 06 nicklas 173   // -------------------------------------------
2664 26 Sep 06 nicklas 174
2664 26 Sep 06 nicklas 175   /**
2664 26 Sep 06 nicklas 176     Set a new {@link SqlResult} object that will be used the next time the
2664 26 Sep 06 nicklas 177     JEP expression is evaluated.
2664 26 Sep 06 nicklas 178     @param result The result object
2664 26 Sep 06 nicklas 179   */
2664 26 Sep 06 nicklas 180   public void setSqlResult(SqlResult result)
2664 26 Sep 06 nicklas 181   {
2664 26 Sep 06 nicklas 182     this.result = result;
2664 26 Sep 06 nicklas 183   }
2664 26 Sep 06 nicklas 184
2664 26 Sep 06 nicklas 185   /**
2664 26 Sep 06 nicklas 186     Get the value of the specified extra value of the current sql result.
2664 26 Sep 06 nicklas 187     @param extraId The extra value ID
4017 28 Nov 07 martin 188      @return an extra value as an Object.
4017 28 Nov 07 martin 189      @throws ParseException If no result has been specified or
4017 28 Nov 07 martin 190        if no extra value was found.
2664 26 Sep 06 nicklas 191   */
2664 26 Sep 06 nicklas 192   public Object xtra(Integer extraId)
2664 26 Sep 06 nicklas 193     throws ParseException
2664 26 Sep 06 nicklas 194   {
2664 26 Sep 06 nicklas 195     if (result == null)
2664 26 Sep 06 nicklas 196     {
2664 26 Sep 06 nicklas 197       throw new ParseException("No result object has been specified for function xtra("+extraId+")");
2664 26 Sep 06 nicklas 198     }
2664 26 Sep 06 nicklas 199     if (extraToIndex == null || extraToIndex.get(extraId) == null)
2664 26 Sep 06 nicklas 200     {
2664 26 Sep 06 nicklas 201       throw new ParseException("Extra value not found for function xtra("+extraId+")");
2664 26 Sep 06 nicklas 202     }
2664 26 Sep 06 nicklas 203     try
2664 26 Sep 06 nicklas 204     {
2664 26 Sep 06 nicklas 205       return result.getObject(extraToIndex.get(extraId));
2664 26 Sep 06 nicklas 206     }
2664 26 Sep 06 nicklas 207     catch (SQLException ex)
2664 26 Sep 06 nicklas 208     {
2664 26 Sep 06 nicklas 209       throw new ParseException(ex.getMessage());
2664 26 Sep 06 nicklas 210     }
2664 26 Sep 06 nicklas 211   }
2664 26 Sep 06 nicklas 212 }