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

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