src/core/net/sf/basedb/util/jep/RawFunction.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
1581 09 Nov 05 nicklas 6
2304 22 May 06 jari 7   This file is part of BASE - BioArray Software Environment.
2304 22 May 06 jari 8   Available at http://base.thep.lu.se/
1581 09 Nov 05 nicklas 9
1581 09 Nov 05 nicklas 10   BASE is free software; you can redistribute it and/or
1581 09 Nov 05 nicklas 11   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 12   as published by the Free Software Foundation; either version 3
1581 09 Nov 05 nicklas 13   of the License, or (at your option) any later version.
1581 09 Nov 05 nicklas 14
1581 09 Nov 05 nicklas 15   BASE is distributed in the hope that it will be useful,
1581 09 Nov 05 nicklas 16   but WITHOUT ANY WARRANTY; without even the implied warranty of
1581 09 Nov 05 nicklas 17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1581 09 Nov 05 nicklas 18   GNU General Public License for more details.
1581 09 Nov 05 nicklas 19
1581 09 Nov 05 nicklas 20   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 21   along with BASE. If not, see <http://www.gnu.org/licenses/>.
1581 09 Nov 05 nicklas 22 */
1581 09 Nov 05 nicklas 23 package net.sf.basedb.util.jep;
1581 09 Nov 05 nicklas 24
2086 17 Mar 06 nicklas 25 import net.sf.basedb.core.BaseException;
5319 20 Apr 10 nicklas 26 import net.sf.basedb.core.DynamicQuery;
2993 01 Dec 06 nicklas 27 import net.sf.basedb.core.PermissionDeniedException;
1581 09 Nov 05 nicklas 28 import net.sf.basedb.core.RawDataType;
1590 11 Nov 05 nicklas 29 import net.sf.basedb.core.DbControl;
1590 11 Nov 05 nicklas 30 import net.sf.basedb.core.Metadata;
1581 09 Nov 05 nicklas 31 import net.sf.basedb.core.data.RawData;
2086 17 Mar 06 nicklas 32 import net.sf.basedb.core.query.Dynamic;
2086 17 Mar 06 nicklas 33 import net.sf.basedb.core.query.Expression;
2981 30 Nov 06 nicklas 34 import net.sf.basedb.util.BioAssaySetUtil;
1581 09 Nov 05 nicklas 35
1581 09 Nov 05 nicklas 36 import java.util.Stack;
2086 17 Mar 06 nicklas 37
2086 17 Mar 06 nicklas 38 import org.nfunk.jep.Node;
1581 09 Nov 05 nicklas 39 import org.nfunk.jep.ParseException;
1581 09 Nov 05 nicklas 40
1590 11 Nov 05 nicklas 41
1581 09 Nov 05 nicklas 42 /**
1584 10 Nov 05 nicklas 43   A JEP function class that adds a <code>raw(string)</code> function to a 
1584 10 Nov 05 nicklas 44   JEP expression parser. The function will look up the value of the raw data 
1581 09 Nov 05 nicklas 45   property with the given name. For example: 
1581 09 Nov 05 nicklas 46   <code>raw('ch1FgMean') - raw('ch1BgMean')</code>
1581 09 Nov 05 nicklas 47   <p>
1581 09 Nov 05 nicklas 48   To be able to use this function it must be registered with the JEP
1584 10 Nov 05 nicklas 49   parser and, before the expression is evaluated, a raw data object must be set.
1584 10 Nov 05 nicklas 50   For example we can evaluate an expression for every raw data object
1584 10 Nov 05 nicklas 51   in a raw bioassay:
1581 09 Nov 05 nicklas 52   
1581 09 Nov 05 nicklas 53   <pre class="code">
1581 09 Nov 05 nicklas 54 DbControl dc = ...
1581 09 Nov 05 nicklas 55 RawBioAssay assay = ...
1581 09 Nov 05 nicklas 56 String expression = "raw('ch1FgMean') - raw('ch1BgMean')";
1581 09 Nov 05 nicklas 57 RawFunction raw = new RawFunction(assay.getRawDataType());
1581 09 Nov 05 nicklas 58 JEP jep = JepUtil.newJep(expression, raw);
1581 09 Nov 05 nicklas 59 DataResultIterator&lt;RawData&gt; result = 
1581 09 Nov 05 nicklas 60    assay.getRawData().iterate(dc);
1581 09 Nov 05 nicklas 61 while (result.hasNext())
1581 09 Nov 05 nicklas 62 {
1581 09 Nov 05 nicklas 63    raw.setRawData(result.next());
1581 09 Nov 05 nicklas 64    double value = jep.getValue();
1581 09 Nov 05 nicklas 65    // Do something with the value
1581 09 Nov 05 nicklas 66 }
1581 09 Nov 05 nicklas 67 result.close();
1581 09 Nov 05 nicklas 68 </pre>
1581 09 Nov 05 nicklas 69
1581 09 Nov 05 nicklas 70   @author Nicklas
1581 09 Nov 05 nicklas 71   @version 2.0
1581 09 Nov 05 nicklas 72   @base.modified $Date$
1584 10 Nov 05 nicklas 73   @see Jep
5319 20 Apr 10 nicklas 74   @see BioAssaySetUtil#createJepExpression(DbControl, String, DynamicQuery)
1581 09 Nov 05 nicklas 75 */
1581 09 Nov 05 nicklas 76 public class RawFunction
2086 17 Mar 06 nicklas 77   implements JepExpressionFunction
1581 09 Nov 05 nicklas 78 {
1581 09 Nov 05 nicklas 79
1581 09 Nov 05 nicklas 80   private final RawDataType rawDataType;
1590 11 Nov 05 nicklas 81   private final Metadata<RawData> metaData;
1590 11 Nov 05 nicklas 82   private final DbControl dc;
2993 01 Dec 06 nicklas 83   private final boolean allowUse;
1581 09 Nov 05 nicklas 84   private int numParameters;
1581 09 Nov 05 nicklas 85   private RawData rawData;
1581 09 Nov 05 nicklas 86
1581 09 Nov 05 nicklas 87   /**
2086 17 Mar 06 nicklas 88     Create a new instance of this function. The new instance cannot be used
2086 17 Mar 06 nicklas 89     to dynamically evaluate expressions. It should only be used for converting
2086 17 Mar 06 nicklas 90     JEP formulas to {@link Expression}:s.
2086 17 Mar 06 nicklas 91     @see Jep#formulaToExpression(String, JepFunction[])
2086 17 Mar 06 nicklas 92   */
2993 01 Dec 06 nicklas 93   public RawFunction(boolean allowUse)
2086 17 Mar 06 nicklas 94   {
2086 17 Mar 06 nicklas 95     this.dc = null;
2086 17 Mar 06 nicklas 96     this.metaData = null;
2086 17 Mar 06 nicklas 97     this.rawDataType = null;
2993 01 Dec 06 nicklas 98     this.allowUse = allowUse;
2086 17 Mar 06 nicklas 99   }
2086 17 Mar 06 nicklas 100   
2086 17 Mar 06 nicklas 101   /**
1581 09 Nov 05 nicklas 102     Create a new instance of this function working with raw data of
1581 09 Nov 05 nicklas 103     the specified raw data type.
1581 09 Nov 05 nicklas 104     @param rawDataType The type of raw data this function uses
1581 09 Nov 05 nicklas 105   */
2993 01 Dec 06 nicklas 106   public RawFunction(DbControl dc, RawDataType rawDataType, boolean allowUse)
1581 09 Nov 05 nicklas 107   {
1590 11 Nov 05 nicklas 108     this.dc = dc;
1581 09 Nov 05 nicklas 109     this.rawDataType = rawDataType;
1590 11 Nov 05 nicklas 110     this.metaData = Metadata.getInstance(RawData.class, rawDataType.getEntityName());
2993 01 Dec 06 nicklas 111     this.allowUse = allowUse;
1581 09 Nov 05 nicklas 112   }
1581 09 Nov 05 nicklas 113   
1581 09 Nov 05 nicklas 114   /*
1581 09 Nov 05 nicklas 115     From the JepFunction interface
1581 09 Nov 05 nicklas 116     -------------------------------------------
1581 09 Nov 05 nicklas 117   */
1581 09 Nov 05 nicklas 118   /**
1581 09 Nov 05 nicklas 119     @return The string "raw"
1581 09 Nov 05 nicklas 120   */
6127 14 Sep 12 nicklas 121   @Override
1581 09 Nov 05 nicklas 122   public String getFunctionName()
1581 09 Nov 05 nicklas 123   {
1581 09 Nov 05 nicklas 124     return "raw";
1581 09 Nov 05 nicklas 125   }
1581 09 Nov 05 nicklas 126   // -------------------------------------------
1581 09 Nov 05 nicklas 127   /*
2086 17 Mar 06 nicklas 128     From the JepExpressionFunction interface
2086 17 Mar 06 nicklas 129     -------------------------------------------
2086 17 Mar 06 nicklas 130   */
2086 17 Mar 06 nicklas 131   /**
2086 17 Mar 06 nicklas 132     Use the {@link Dynamic#rawData(String)} method to create an
2086 17 Mar 06 nicklas 133     expression referencing a raw data property.
2086 17 Mar 06 nicklas 134   */
6127 14 Sep 12 nicklas 135   @Override
2086 17 Mar 06 nicklas 136   public Expression toExpression(Node node)
2086 17 Mar 06 nicklas 137   {
2993 01 Dec 06 nicklas 138     if (!allowUse)
2993 01 Dec 06 nicklas 139     {
2993 01 Dec 06 nicklas 140       throw new PermissionDeniedException("Not allowed to use 'raw' function with merged data");
2993 01 Dec 06 nicklas 141     }
2086 17 Mar 06 nicklas 142     int numChildren = node.jjtGetNumChildren();
2086 17 Mar 06 nicklas 143     if (numChildren != 1)
2086 17 Mar 06 nicklas 144     {
2086 17 Mar 06 nicklas 145       throw new BaseException("Invalid number of expressions for 'raw' function: " + numChildren);
2086 17 Mar 06 nicklas 146     }
2086 17 Mar 06 nicklas 147     return Dynamic.rawData(Jep.nodeToString(node.jjtGetChild(0)));
2086 17 Mar 06 nicklas 148   }
2086 17 Mar 06 nicklas 149   // -------------------------------------------
2086 17 Mar 06 nicklas 150   /*
1581 09 Nov 05 nicklas 151     From the PostfixMathCommandI interface
1581 09 Nov 05 nicklas 152     -------------------------------------------
1581 09 Nov 05 nicklas 153   */
1581 09 Nov 05 nicklas 154   /**
1581 09 Nov 05 nicklas 155     @return Always 1
1581 09 Nov 05 nicklas 156   */
6127 14 Sep 12 nicklas 157   @Override
1581 09 Nov 05 nicklas 158   public int getNumberOfParameters()
1581 09 Nov 05 nicklas 159   {
1581 09 Nov 05 nicklas 160     return 1;
1581 09 Nov 05 nicklas 161   }
6127 14 Sep 12 nicklas 162   @Override
1581 09 Nov 05 nicklas 163   public void setCurNumberOfParameters(int n)
1581 09 Nov 05 nicklas 164   {
1581 09 Nov 05 nicklas 165     this.numParameters = n;
1581 09 Nov 05 nicklas 166   }
6127 14 Sep 12 nicklas 167   @Override
2474 31 Jul 06 nicklas 168   public boolean checkNumberOfParameters(int n)
2474 31 Jul 06 nicklas 169   {
2474 31 Jul 06 nicklas 170     return n == 1;
2474 31 Jul 06 nicklas 171   }
6127 14 Sep 12 nicklas 172   @Override
6875 20 Apr 15 nicklas 173   @SuppressWarnings({"unchecked", "rawtypes"})
1581 09 Nov 05 nicklas 174   public void run(Stack stack)
1581 09 Nov 05 nicklas 175     throws ParseException
1581 09 Nov 05 nicklas 176   {
1581 09 Nov 05 nicklas 177     if (stack == null || stack.empty()) 
1581 09 Nov 05 nicklas 178     {
1581 09 Nov 05 nicklas 179       throw new ParseException("Stack is empty");
1581 09 Nov 05 nicklas 180     }
1581 09 Nov 05 nicklas 181     Object propertyName = stack.pop();
1581 09 Nov 05 nicklas 182     if (propertyName instanceof String)
1581 09 Nov 05 nicklas 183     {
1581 09 Nov 05 nicklas 184       stack.push(raw((String)propertyName));
1581 09 Nov 05 nicklas 185     }
1581 09 Nov 05 nicklas 186     else
1581 09 Nov 05 nicklas 187     {
1581 09 Nov 05 nicklas 188       throw new ParseException("Invalid parameter type: " + propertyName + "; expected string");
1581 09 Nov 05 nicklas 189     }
1581 09 Nov 05 nicklas 190   }
1581 09 Nov 05 nicklas 191   // -------------------------------------------
1581 09 Nov 05 nicklas 192
1581 09 Nov 05 nicklas 193   /**
1581 09 Nov 05 nicklas 194     Get the raw data type this function uses.
1581 09 Nov 05 nicklas 195   */
1581 09 Nov 05 nicklas 196   public RawDataType getRawDataType()
1581 09 Nov 05 nicklas 197   {
1581 09 Nov 05 nicklas 198     return rawDataType;
1581 09 Nov 05 nicklas 199   }
1581 09 Nov 05 nicklas 200   /**
1581 09 Nov 05 nicklas 201     Set a new raw data object that will be used the next time the
1581 09 Nov 05 nicklas 202     JEP expression is evaluated.
1581 09 Nov 05 nicklas 203     @param rawData The raw data object to use
1581 09 Nov 05 nicklas 204   */
1581 09 Nov 05 nicklas 205   public void setRawData(RawData rawData)
1581 09 Nov 05 nicklas 206   {
1581 09 Nov 05 nicklas 207     this.rawData = rawData;
1581 09 Nov 05 nicklas 208   }
1581 09 Nov 05 nicklas 209   /**
1581 09 Nov 05 nicklas 210     Get the current raw data object used when evaluating the JEP expression.
1581 09 Nov 05 nicklas 211   */
1581 09 Nov 05 nicklas 212   public RawData getRawData()
1581 09 Nov 05 nicklas 213   {
1581 09 Nov 05 nicklas 214     return rawData;
1581 09 Nov 05 nicklas 215   }
1581 09 Nov 05 nicklas 216   
1581 09 Nov 05 nicklas 217   /**
1581 09 Nov 05 nicklas 218     Get the value of the specified property of the current raw data object.
1581 09 Nov 05 nicklas 219     This method uses Hibernate metadata to find the value.
4020 29 Nov 07 martin 220     @param propertyName The name of the raw data property. Null is not allowed.
4020 29 Nov 07 martin 221      @return The value as a java.lang.Object 
4020 29 Nov 07 martin 222      @throws ParseException If required arguments is null 
1581 09 Nov 05 nicklas 223   */
1581 09 Nov 05 nicklas 224   public Object raw(String propertyName)
1581 09 Nov 05 nicklas 225     throws ParseException
1581 09 Nov 05 nicklas 226   {
1581 09 Nov 05 nicklas 227     if (rawData == null || propertyName == null)
1581 09 Nov 05 nicklas 228     {
1581 09 Nov 05 nicklas 229       throw new ParseException("No raw data object has been specified for function raw('"+propertyName+"')");
1581 09 Nov 05 nicklas 230     }
5319 20 Apr 10 nicklas 231     return metaData.getPropertyPath(propertyName, false).getValue(dc, rawData);
1581 09 Nov 05 nicklas 232   }
1581 09 Nov 05 nicklas 233 }