src/core/net/sf/basedb/util/parser/JepMapper.java

Code
Comments
Other
Rev Date Author Line
2317 24 May 06 nicklas 1 /**
2317 24 May 06 nicklas 2   $Id$
2317 24 May 06 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2006, 2007 Nicklas Nordborg
2317 24 May 06 nicklas 5
2317 24 May 06 nicklas 6   This file is part of BASE - BioArray Software Environment.
2317 24 May 06 nicklas 7   Available at http://base.thep.lu.se/
2317 24 May 06 nicklas 8
2317 24 May 06 nicklas 9   BASE is free software; you can redistribute it and/or
2317 24 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
2317 24 May 06 nicklas 12   of the License, or (at your option) any later version.
2317 24 May 06 nicklas 13
2317 24 May 06 nicklas 14   BASE is distributed in the hope that it will be useful,
2317 24 May 06 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
2317 24 May 06 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2317 24 May 06 nicklas 17   GNU General Public License for more details.
2317 24 May 06 nicklas 18
2317 24 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/>.
2317 24 May 06 nicklas 21 */
2317 24 May 06 nicklas 22 package net.sf.basedb.util.parser;
2317 24 May 06 nicklas 23
3023 12 Dec 06 nicklas 24 import java.text.NumberFormat;
7667 21 Mar 19 nicklas 25 import java.util.Date;
2655 22 Sep 06 nicklas 26 import java.util.List;
2317 24 May 06 nicklas 27 import org.nfunk.jep.JEP;
2317 24 May 06 nicklas 28
7664 20 Mar 19 nicklas 29 import net.sf.basedb.core.Type;
7667 21 Mar 19 nicklas 30 import net.sf.basedb.util.formatter.Formatter;
2317 24 May 06 nicklas 31 import net.sf.basedb.util.jep.Jep;
5899 06 Dec 11 nicklas 32 import net.sf.basedb.util.jep.JepFunction;
5773 29 Sep 11 nicklas 33 import net.sf.basedb.util.jep.LeftFunction;
2317 24 May 06 nicklas 34 import net.sf.basedb.util.parser.FlatFileParser.Data;
2317 24 May 06 nicklas 35
2317 24 May 06 nicklas 36 /**
2317 24 May 06 nicklas 37   A mapper that uses Jep to calculate the final value. It should be used
2317 24 May 06 nicklas 38   for numerical values that needs to be transformed before beeing inserted
2317 24 May 06 nicklas 39   into the database. For example, if a file contains the radius of a spot 
2317 24 May 06 nicklas 40   instead of the diameter, it could be mapped as <code>=2 * col('Radius')</code>.
2317 24 May 06 nicklas 41   <p>
2317 24 May 06 nicklas 42   It can also be used for concatenating string values but syntax with backslashes 
2317 24 May 06 nicklas 43   has better performance. The following mapping expressions are equivalent,
2317 24 May 06 nicklas 44   but we recommend using the first one:
6881 21 Apr 15 nicklas 45   <pre class="code">
2317 24 May 06 nicklas 46 \Name\:\ID\
2317 24 May 06 nicklas 47 =col('Name')+':'+col('ID')
2317 24 May 06 nicklas 48 =\Name\+':'+\ID\
2317 24 May 06 nicklas 49 </pre>
2317 24 May 06 nicklas 50    
2317 24 May 06 nicklas 51   @author nicklas
2317 24 May 06 nicklas 52   @version 2.0
2317 24 May 06 nicklas 53   @base.modified $Date$
2317 24 May 06 nicklas 54 */
2317 24 May 06 nicklas 55 public class JepMapper
2317 24 May 06 nicklas 56   implements Mapper
2317 24 May 06 nicklas 57 {
2317 24 May 06 nicklas 58
2317 24 May 06 nicklas 59   private final String expression;
2317 24 May 06 nicklas 60   private final JEP parser;
2317 24 May 06 nicklas 61   private final ColFunction colFunction;
3618 01 Aug 07 nicklas 62   private final LineNoFunction lineNoFunction;
3618 01 Aug 07 nicklas 63   private final boolean hasLineNo;
3618 01 Aug 07 nicklas 64   private final DataNoFunction dataNoFunction;
3618 01 Aug 07 nicklas 65   private final boolean hasDataNo;
3023 12 Dec 06 nicklas 66   private final NumberFormat numberFormat;
7667 21 Mar 19 nicklas 67   private final Formatter<Date> dateFormat;
2317 24 May 06 nicklas 68   
2317 24 May 06 nicklas 69   /**
2317 24 May 06 nicklas 70     Create a new JepMapper.
2317 24 May 06 nicklas 71     @param expression The JEP expression
2317 24 May 06 nicklas 72     @param columnHeaders A map from column names to column indexes 
2317 24 May 06 nicklas 73   */
2655 22 Sep 06 nicklas 74   public JepMapper(String expression, List<String> columnHeaders)
2317 24 May 06 nicklas 75   {
7668 21 Mar 19 nicklas 76     this(expression, columnHeaders, null, null, false, (JepFunction[])null);
3023 12 Dec 06 nicklas 77   }
3023 12 Dec 06 nicklas 78   
7668 21 Mar 19 nicklas 79   /**
7668 21 Mar 19 nicklas 80     @deprecated In 3.15, use {@link JepMapper#JepMapper(String, List, NumberFormat, Formatter, boolean, JepFunction...)} instead
7668 21 Mar 19 nicklas 81   */
7668 21 Mar 19 nicklas 82   @Deprecated
3023 12 Dec 06 nicklas 83   public JepMapper(String expression, List<String> columnHeaders, NumberFormat numberFormat)
3023 12 Dec 06 nicklas 84   {
7668 21 Mar 19 nicklas 85     this(expression, columnHeaders, numberFormat, null, false, (JepFunction[])null);
4104 28 Jan 08 nicklas 86   }
4104 28 Jan 08 nicklas 87
7668 21 Mar 19 nicklas 88   /**
7668 21 Mar 19 nicklas 89     @deprecated In 3.15, use {@link JepMapper#JepMapper(String, List, NumberFormat, Formatter, boolean, JepFunction...)} instead
7668 21 Mar 19 nicklas 90   */
7668 21 Mar 19 nicklas 91   @Deprecated
4104 28 Jan 08 nicklas 92   public JepMapper(String expression, List<String> columnHeaders, NumberFormat numberFormat,
5899 06 Dec 11 nicklas 93       boolean ignoreNonExistingColumns)
4104 28 Jan 08 nicklas 94   {
7667 21 Mar 19 nicklas 95     this(expression, columnHeaders, numberFormat, null, ignoreNonExistingColumns, (JepFunction[])null);
5899 06 Dec 11 nicklas 96   }
7667 21 Mar 19 nicklas 97   
5899 06 Dec 11 nicklas 98   /**
7667 21 Mar 19 nicklas 99     
5899 06 Dec 11 nicklas 100     @since 3.1
7668 21 Mar 19 nicklas 101     @deprecated In 3.15, use {@link JepMapper#JepMapper(String, List, NumberFormat, Formatter, boolean, JepFunction...)} instead
5899 06 Dec 11 nicklas 102   */
7668 21 Mar 19 nicklas 103   @Deprecated
5899 06 Dec 11 nicklas 104   public JepMapper(String expression, List<String> columnHeaders, NumberFormat numberFormat,
5899 06 Dec 11 nicklas 105     boolean ignoreNonExistingColumns, JepFunction... functions)
5899 06 Dec 11 nicklas 106   {
7668 21 Mar 19 nicklas 107     this(expression, columnHeaders, numberFormat, null, ignoreNonExistingColumns, functions);
7667 21 Mar 19 nicklas 108   }
7667 21 Mar 19 nicklas 109
7667 21 Mar 19 nicklas 110   /**
7667 21 Mar 19 nicklas 111   
7667 21 Mar 19 nicklas 112     @since 3.15
7667 21 Mar 19 nicklas 113   */
7667 21 Mar 19 nicklas 114   public JepMapper(String expression, List<String> columnHeaders, NumberFormat numberFormat,
7667 21 Mar 19 nicklas 115     Formatter<Date> dateFormat, boolean ignoreNonExistingColumns, JepFunction... functions)
7667 21 Mar 19 nicklas 116   {
2317 24 May 06 nicklas 117     this.expression = expression;
3023 12 Dec 06 nicklas 118     this.numberFormat = numberFormat;
7667 21 Mar 19 nicklas 119     this.dateFormat = dateFormat;
7667 21 Mar 19 nicklas 120     this.colFunction = new ColFunction(columnHeaders, numberFormat, dateFormat);
4104 28 Jan 08 nicklas 121     colFunction.setIgnoreNonExistingColumns(ignoreNonExistingColumns);
3618 01 Aug 07 nicklas 122     this.lineNoFunction = expression.contains("lineNo()") ? new LineNoFunction() : null;
3618 01 Aug 07 nicklas 123     this.hasLineNo = lineNoFunction != null;
3618 01 Aug 07 nicklas 124     this.dataNoFunction = expression.contains("dataNo()") ? new DataNoFunction() : null;
3618 01 Aug 07 nicklas 125     this.hasDataNo = dataNoFunction != null;
2317 24 May 06 nicklas 126     // Replace: \ColumnName\ with: col('ColumnName')
2317 24 May 06 nicklas 127     expression = expression.replaceAll("\\\\([^\\\\]*)\\\\", "col('$1')");
5899 06 Dec 11 nicklas 128     
5899 06 Dec 11 nicklas 129     JepFunction[] extraFunctions = new JepFunction[4 + (functions == null ? 0 : functions.length)];
5899 06 Dec 11 nicklas 130     extraFunctions[0] = colFunction;
5899 06 Dec 11 nicklas 131     extraFunctions[1] = lineNoFunction;
5899 06 Dec 11 nicklas 132     extraFunctions[2] = dataNoFunction;
5899 06 Dec 11 nicklas 133     extraFunctions[3] = new LeftFunction();
5899 06 Dec 11 nicklas 134     if (functions != null)
5899 06 Dec 11 nicklas 135     {
5899 06 Dec 11 nicklas 136       System.arraycopy(functions, 0, extraFunctions, 4, functions.length);
5899 06 Dec 11 nicklas 137     }
5899 06 Dec 11 nicklas 138     this.parser = Jep.newJep(expression, extraFunctions);
2317 24 May 06 nicklas 139   }
2317 24 May 06 nicklas 140   
4104 28 Jan 08 nicklas 141   
2317 24 May 06 nicklas 142   /*
2317 24 May 06 nicklas 143     From the Mapper interface
2317 24 May 06 nicklas 144     -------------------------------------------
2317 24 May 06 nicklas 145   */
6127 14 Sep 12 nicklas 146   @Override
7666 20 Mar 19 nicklas 147   @Deprecated
2317 24 May 06 nicklas 148   public String getValue(Data data)
2317 24 May 06 nicklas 149   {
7666 20 Mar 19 nicklas 150     return getString(data);
7666 20 Mar 19 nicklas 151   }
7666 20 Mar 19 nicklas 152   @Override
7666 20 Mar 19 nicklas 153   public String getString(Data data)
7666 20 Mar 19 nicklas 154   {
7664 20 Mar 19 nicklas 155     setData(data, Type.STRING);
2655 22 Sep 06 nicklas 156     // Workaround for bug in JEP error handling 
2655 22 Sep 06 nicklas 157     // See http://sourceforge.net/tracker/index.php?func=detail&atid=382402&aid=1563324&group_id=24711
2655 22 Sep 06 nicklas 158     if (parser.hasError()) Jep.clearErrorList(parser);
2317 24 May 06 nicklas 159     Object value = parser.getValueAsObject();
2317 24 May 06 nicklas 160     return value == null ? null : value.toString();
2317 24 May 06 nicklas 161   }
6127 14 Sep 12 nicklas 162   @Override
2317 24 May 06 nicklas 163   public Integer getInt(Data data)
2317 24 May 06 nicklas 164   {
7664 20 Mar 19 nicklas 165     setData(data, Type.INT);
2655 22 Sep 06 nicklas 166     if (parser.hasError()) Jep.clearErrorList(parser);
3023 12 Dec 06 nicklas 167     return Integer.valueOf((int)parser.getValue());
2317 24 May 06 nicklas 168   }
6127 14 Sep 12 nicklas 169   @Override
7668 21 Mar 19 nicklas 170   public Long getLong(Data data)
7668 21 Mar 19 nicklas 171   {
7668 21 Mar 19 nicklas 172     setData(data, Type.LONG);
7668 21 Mar 19 nicklas 173     if (parser.hasError()) Jep.clearErrorList(parser);
7668 21 Mar 19 nicklas 174     return Long.valueOf((long)parser.getValue());
7668 21 Mar 19 nicklas 175   }
7668 21 Mar 19 nicklas 176   @Override
2317 24 May 06 nicklas 177   public Float getFloat(Data data)
2317 24 May 06 nicklas 178   {
7664 20 Mar 19 nicklas 179     setData(data, Type.FLOAT);
2655 22 Sep 06 nicklas 180     if (parser.hasError()) Jep.clearErrorList(parser);
3023 12 Dec 06 nicklas 181     return Float.valueOf((float)parser.getValue());
2317 24 May 06 nicklas 182   }
7667 21 Mar 19 nicklas 183   @Override
7668 21 Mar 19 nicklas 184   public Double getDouble(Data data)
7668 21 Mar 19 nicklas 185   {
7668 21 Mar 19 nicklas 186     setData(data, Type.DOUBLE);
7668 21 Mar 19 nicklas 187     if (parser.hasError()) Jep.clearErrorList(parser);
7668 21 Mar 19 nicklas 188     return parser.getValue();
7668 21 Mar 19 nicklas 189   }
7668 21 Mar 19 nicklas 190   @Override
7667 21 Mar 19 nicklas 191   public Date getDate(Data data)
7667 21 Mar 19 nicklas 192   {
7667 21 Mar 19 nicklas 193     setData(data, Type.DATE);
7667 21 Mar 19 nicklas 194     if (parser.hasError()) Jep.clearErrorList(parser);
7667 21 Mar 19 nicklas 195     Object value = parser.getValueAsObject();
7667 21 Mar 19 nicklas 196     return (Date)value;
7667 21 Mar 19 nicklas 197   }
7667 21 Mar 19 nicklas 198
2317 24 May 06 nicklas 199   // -------------------------------------------
2317 24 May 06 nicklas 200   /*
2317 24 May 06 nicklas 201     From the Object class
2317 24 May 06 nicklas 202     -------------------------------------------
2317 24 May 06 nicklas 203   */
6127 14 Sep 12 nicklas 204   @Override
2317 24 May 06 nicklas 205   public String toString()
2317 24 May 06 nicklas 206   {
2317 24 May 06 nicklas 207     return "=" + expression;
2317 24 May 06 nicklas 208   }
2317 24 May 06 nicklas 209   // -------------------------------------------
2317 24 May 06 nicklas 210
7664 20 Mar 19 nicklas 211   private void setData(Data data, Type valueType)
3618 01 Aug 07 nicklas 212   {
7664 20 Mar 19 nicklas 213     colFunction.setData(data, valueType);
3618 01 Aug 07 nicklas 214     if (hasLineNo) lineNoFunction.setData(data);
3618 01 Aug 07 nicklas 215     if (hasDataNo) dataNoFunction.setData(data);
3618 01 Aug 07 nicklas 216   }
2317 24 May 06 nicklas 217 }