src/core/net/sf/basedb/util/export/spotdata/AdvancedFieldConverter.java

Code
Comments
Other
Rev Date Author Line
5381 05 Aug 10 nicklas 1 /**
5381 05 Aug 10 nicklas 2   $Id$
5381 05 Aug 10 nicklas 3
5381 05 Aug 10 nicklas 4   Copyright (C) 2010 Nicklas Nordborg
5381 05 Aug 10 nicklas 5
5381 05 Aug 10 nicklas 6   This file is part of BASE - BioArray Software Environment.
5381 05 Aug 10 nicklas 7   Available at http://base.thep.lu.se/
5381 05 Aug 10 nicklas 8
5381 05 Aug 10 nicklas 9   BASE is free software; you can redistribute it and/or
5381 05 Aug 10 nicklas 10   modify it under the terms of the GNU General Public License
5381 05 Aug 10 nicklas 11   as published by the Free Software Foundation; either version 3
5381 05 Aug 10 nicklas 12   of the License, or (at your option) any later version.
5381 05 Aug 10 nicklas 13
5381 05 Aug 10 nicklas 14   BASE is distributed in the hope that it will be useful,
5381 05 Aug 10 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
5381 05 Aug 10 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5381 05 Aug 10 nicklas 17   GNU General Public License for more details.
5381 05 Aug 10 nicklas 18
5381 05 Aug 10 nicklas 19   You should have received a copy of the GNU General Public License
5381 05 Aug 10 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
5381 05 Aug 10 nicklas 21 */
5381 05 Aug 10 nicklas 22 package net.sf.basedb.util.export.spotdata;
5381 05 Aug 10 nicklas 23
5381 05 Aug 10 nicklas 24 import java.util.HashMap;
5381 05 Aug 10 nicklas 25 import java.util.Map;
5381 05 Aug 10 nicklas 26 import java.util.regex.Matcher;
5381 05 Aug 10 nicklas 27 import java.util.regex.Pattern;
5381 05 Aug 10 nicklas 28
5381 05 Aug 10 nicklas 29 import net.sf.basedb.core.BioAssaySet;
5381 05 Aug 10 nicklas 30 import net.sf.basedb.core.DbControl;
5381 05 Aug 10 nicklas 31 import net.sf.basedb.core.InvalidDataException;
5381 05 Aug 10 nicklas 32 import net.sf.basedb.core.ItemNotFoundException;
5381 05 Aug 10 nicklas 33 import net.sf.basedb.core.Type;
5381 05 Aug 10 nicklas 34 import net.sf.basedb.core.ExtraValue.CoordinateType;
5381 05 Aug 10 nicklas 35 import net.sf.basedb.util.Values;
5381 05 Aug 10 nicklas 36
5381 05 Aug 10 nicklas 37 /**
5381 05 Aug 10 nicklas 38   Field converter implementation that gives more detailed control how
5381 05 Aug 10 nicklas 39   fields are converted and used in the export. The implementation 
5381 05 Aug 10 nicklas 40   builds on the {@link StandardFieldConverter} which is used as
5381 05 Aug 10 nicklas 41   a fallback. The advanced options can be accessed by using formula-like
5381 05 Aug 10 nicklas 42   field "names" as shown below. In most cases the "title" parameter
5381 05 Aug 10 nicklas 43   is optional. If not given, the name is used as the title.
5381 05 Aug 10 nicklas 44   
5381 05 Aug 10 nicklas 45   <ul>
5381 05 Aug 10 nicklas 46   <li>=property("name", ["title"]): Lookup a static property with the given
5381 05 Aug 10 nicklas 47     name. Can be used on assay, reporter and spot (=raw data properties)
5381 05 Aug 10 nicklas 48     fields.
5381 05 Aug 10 nicklas 49   <li>=factor("name" [,"title"]): Lookup an experimental factor with the 
5381 05 Aug 10 nicklas 50     given name or external id. Can be used in 
5381 05 Aug 10 nicklas 51     {@link #getAssayField(String, boolean)}.
5381 05 Aug 10 nicklas 52   <li>=annotation("name" [,"title"]): Lookup an assay annotation with the
5381 05 Aug 10 nicklas 53     given name or external id. Can be used in 
5381 05 Aug 10 nicklas 54     {@link #getAssayField(String, boolean)}. 
5381 05 Aug 10 nicklas 55   <li>=xtra("name" [,"title"]): Lookup an extra value with the given name
5381 05 Aug 10 nicklas 56     or external id. Can be used in {@link #getReporterField(String, boolean)}
5381 05 Aug 10 nicklas 57     and {@link #getSpotField(String, boolean)}.
5381 05 Aug 10 nicklas 58   <li>=formula("name" [,"title"]): Lookup a formula with the given name.
5381 05 Aug 10 nicklas 59     Can be used in {@link #getReporterField(String, boolean)} and 
5381 05 Aug 10 nicklas 60     {@link #getSpotField(String, boolean)}.
5381 05 Aug 10 nicklas 61   <li>=jep("jep expression", "title" [,"datatype"]): Use the given JEP formula
5381 05 Aug 10 nicklas 62     to calculate the exported value. Can be used in {@link 
5381 05 Aug 10 nicklas 63     #getReporterField(String, boolean)} and {@link #getSpotField(String, boolean)}.
5381 05 Aug 10 nicklas 64     The "title" is required. The "datatype" is optional. If not given "string" will
5381 05 Aug 10 nicklas 65     be used. Valid values are constants from the {@link Type} enumeration 
5381 05 Aug 10 nicklas 66     (case-insensitive).
5381 05 Aug 10 nicklas 67   </ul>
5381 05 Aug 10 nicklas 68   
5381 05 Aug 10 nicklas 69   Field names that doesn't start with an equal character (=) are passed on to
5381 05 Aug 10 nicklas 70   the {@link StandardFieldConverter}.
5381 05 Aug 10 nicklas 71   
5381 05 Aug 10 nicklas 72   @author Nicklas
5381 05 Aug 10 nicklas 73   @since 2.16
5381 05 Aug 10 nicklas 74   @base.modified $Date$
5381 05 Aug 10 nicklas 75 */
5381 05 Aug 10 nicklas 76 public class AdvancedFieldConverter
5381 05 Aug 10 nicklas 77   extends StandardFieldConverter
5381 05 Aug 10 nicklas 78 {
5381 05 Aug 10 nicklas 79
5381 05 Aug 10 nicklas 80   private Map<String, Pattern> patterns;
5381 05 Aug 10 nicklas 81   
5381 05 Aug 10 nicklas 82   /**
5381 05 Aug 10 nicklas 83     Create a new advanced field converter.
5381 05 Aug 10 nicklas 84     @param dc A DbControl to use for database access
5381 05 Aug 10 nicklas 85     @param source The source bioassay set
5381 05 Aug 10 nicklas 86   */
5381 05 Aug 10 nicklas 87   public AdvancedFieldConverter(DbControl dc, BioAssaySet source)
5381 05 Aug 10 nicklas 88   {
5381 05 Aug 10 nicklas 89     super(dc, source);
5381 05 Aug 10 nicklas 90     this.patterns = new HashMap<String, Pattern>();
5381 05 Aug 10 nicklas 91   }
5381 05 Aug 10 nicklas 92   /*
5381 05 Aug 10 nicklas 93     From the ExportableFieldConverter interface
5381 05 Aug 10 nicklas 94     -------------------------------------------
5381 05 Aug 10 nicklas 95   */
5381 05 Aug 10 nicklas 96   @Override
5381 05 Aug 10 nicklas 97   public AssayField getAssayField(String name, boolean required)
5381 05 Aug 10 nicklas 98   {
5381 05 Aug 10 nicklas 99     AssayField af = null;
5381 05 Aug 10 nicklas 100     if (name.startsWith("="))
5381 05 Aug 10 nicklas 101     {
5381 05 Aug 10 nicklas 102       af = getAdvancedAssayField(name, required);
5381 05 Aug 10 nicklas 103     }
5381 05 Aug 10 nicklas 104     else
5381 05 Aug 10 nicklas 105     {
5381 05 Aug 10 nicklas 106       af = super.getAssayField(name, required);
5381 05 Aug 10 nicklas 107     }
5381 05 Aug 10 nicklas 108     return af;
5381 05 Aug 10 nicklas 109   }
5381 05 Aug 10 nicklas 110
5381 05 Aug 10 nicklas 111   @Override
5381 05 Aug 10 nicklas 112   public DynamicField getReporterField(String name, boolean required)
5381 05 Aug 10 nicklas 113   {
5381 05 Aug 10 nicklas 114     DynamicField df = null;
5381 05 Aug 10 nicklas 115     if (name.startsWith("="))
5381 05 Aug 10 nicklas 116     {
5381 05 Aug 10 nicklas 117       df = getAdvancedReporterField(name, required);
5381 05 Aug 10 nicklas 118     }
5381 05 Aug 10 nicklas 119     else
5381 05 Aug 10 nicklas 120     {
5381 05 Aug 10 nicklas 121       df = super.getReporterField(name, required);
5381 05 Aug 10 nicklas 122     }
5381 05 Aug 10 nicklas 123     return df;
5381 05 Aug 10 nicklas 124   }
5381 05 Aug 10 nicklas 125
5381 05 Aug 10 nicklas 126   @Override
5381 05 Aug 10 nicklas 127   public DynamicField getSpotField(String name, boolean required)
5381 05 Aug 10 nicklas 128   {
5381 05 Aug 10 nicklas 129     DynamicField df = null;
5381 05 Aug 10 nicklas 130     if (name.startsWith("="))
5381 05 Aug 10 nicklas 131     {
5381 05 Aug 10 nicklas 132       df = getAdvancedSpotField(name, required);
5381 05 Aug 10 nicklas 133     }
5381 05 Aug 10 nicklas 134     else
5381 05 Aug 10 nicklas 135     {
5381 05 Aug 10 nicklas 136       df = super.getSpotField(name, required);
5381 05 Aug 10 nicklas 137     }
5381 05 Aug 10 nicklas 138     return df;
5381 05 Aug 10 nicklas 139   }
5381 05 Aug 10 nicklas 140   // ------------------------------------
5381 05 Aug 10 nicklas 141   
5381 05 Aug 10 nicklas 142   /**
5381 05 Aug 10 nicklas 143     Convert an expression to an assay field. Supported expressions are
5381 05 Aug 10 nicklas 144     listed below. The "title" parameter is optional in all cases.
5381 05 Aug 10 nicklas 145     <ul>
5381 05 Aug 10 nicklas 146     <li>=property("name" [,"title"]): Get the value of the property with the
5381 05 Aug 10 nicklas 147       given name.
5381 05 Aug 10 nicklas 148     <li>=factor("name" [,"title"]): Get the value of the experimental factor
5381 05 Aug 10 nicklas 149       with the given name or external id.
5381 05 Aug 10 nicklas 150     <li>=annotation("name" [,"title"]): Get the value of the assay annotation
5381 05 Aug 10 nicklas 151       with the given name or external id.
5381 05 Aug 10 nicklas 152     </ul>
5381 05 Aug 10 nicklas 153   */
5381 05 Aug 10 nicklas 154   protected AssayField getAdvancedAssayField(String expression, boolean required)
5381 05 Aug 10 nicklas 155   {
5381 05 Aug 10 nicklas 156     AssayField af = null;
5381 05 Aug 10 nicklas 157     Pattern p = null;
5381 05 Aug 10 nicklas 158     Matcher m = null;
5381 05 Aug 10 nicklas 159     
5381 05 Aug 10 nicklas 160     // Check: =property("name", "title")
5381 05 Aug 10 nicklas 161     p = getPattern("property", 1, 1);  
5381 05 Aug 10 nicklas 162     m = p.matcher(expression);
5381 05 Aug 10 nicklas 163     if (m.matches())
5381 05 Aug 10 nicklas 164     {
5381 05 Aug 10 nicklas 165       String name = m.group(1);
5381 05 Aug 10 nicklas 166       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 167       af = getAssayPropertyField(name, title);
5381 05 Aug 10 nicklas 168       if (af == null && required) 
5381 05 Aug 10 nicklas 169       {
5381 05 Aug 10 nicklas 170         throw new ItemNotFoundException("Unknown property in assay field expression: " + expression);
5381 05 Aug 10 nicklas 171       }
5381 05 Aug 10 nicklas 172       return af;
5381 05 Aug 10 nicklas 173     }
5381 05 Aug 10 nicklas 174     
5381 05 Aug 10 nicklas 175     // Check: =factor("name", "title")
5381 05 Aug 10 nicklas 176     p = getPattern("factor", 1, 1);  
5381 05 Aug 10 nicklas 177     m = p.matcher(expression);
5381 05 Aug 10 nicklas 178     if (m.matches())
5381 05 Aug 10 nicklas 179     {
5381 05 Aug 10 nicklas 180       String name = m.group(1);
5381 05 Aug 10 nicklas 181       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 182       af = getExperimentalFactorField(name, title);
5381 05 Aug 10 nicklas 183       if (af == null && required) 
5381 05 Aug 10 nicklas 184       {
5381 05 Aug 10 nicklas 185         throw new ItemNotFoundException("Unknown experimental factor in assay field expression: " + expression);
5381 05 Aug 10 nicklas 186       }
5381 05 Aug 10 nicklas 187       return af;
5381 05 Aug 10 nicklas 188     }
5381 05 Aug 10 nicklas 189
5381 05 Aug 10 nicklas 190     // Check: =annotation("name", "title")
5381 05 Aug 10 nicklas 191     p = getPattern("annotation", 1, 1);  
5381 05 Aug 10 nicklas 192     m = p.matcher(expression);
5381 05 Aug 10 nicklas 193     if (m.matches())
5381 05 Aug 10 nicklas 194     {
5381 05 Aug 10 nicklas 195       String name = m.group(1);
5381 05 Aug 10 nicklas 196       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 197       af = getAssayAnnotationField(name, title);
5381 05 Aug 10 nicklas 198       if (af == null && required) 
5381 05 Aug 10 nicklas 199       {
5381 05 Aug 10 nicklas 200         throw new ItemNotFoundException("Unknown annotation in assay field expression: " + expression);
5381 05 Aug 10 nicklas 201       }
5381 05 Aug 10 nicklas 202       return af;
5381 05 Aug 10 nicklas 203     }
5381 05 Aug 10 nicklas 204     
5381 05 Aug 10 nicklas 205     if (af == null && required)
5381 05 Aug 10 nicklas 206     {
5381 05 Aug 10 nicklas 207       throw new InvalidDataException("Invalid assay field expression: " + expression);
5381 05 Aug 10 nicklas 208     }
5381 05 Aug 10 nicklas 209     return af;
5381 05 Aug 10 nicklas 210   }
5381 05 Aug 10 nicklas 211   
5381 05 Aug 10 nicklas 212   /**
5381 05 Aug 10 nicklas 213     Convert an expression to a reporter field. Supported expressions are
5381 05 Aug 10 nicklas 214     listed below. The "title" parameter is optional in the "jep" expression.
5381 05 Aug 10 nicklas 215     <ul>
5381 05 Aug 10 nicklas 216     <li>=property("name" [,"title"]): Get the value of the reporter property 
5381 05 Aug 10 nicklas 217       with the given name.
5381 05 Aug 10 nicklas 218     <li>=formula("name" [,"title"]): Get the value of the formula 
5381 05 Aug 10 nicklas 219       with the given name. The formula should only use
5381 05 Aug 10 nicklas 220       properties that are related to the reporter and it's position.
5381 05 Aug 10 nicklas 221     <li>=xtra("name" [,"title"]): Get the value of the extra value with
5381 05 Aug 10 nicklas 222       the given name or external id. The extra value should be a 
5381 05 Aug 10 nicklas 223       position-based extra value.
5381 05 Aug 10 nicklas 224     <li>=jep("expression", "title" [,"datatype"]): Calculate the value using the
5381 05 Aug 10 nicklas 225       given JEP expression. A title is required. The datatype is optional
5381 05 Aug 10 nicklas 226       (default is STRING). Valid datatypes are those defined by the
5381 05 Aug 10 nicklas 227       {@link Type} enumeration.
5381 05 Aug 10 nicklas 228     </ul>
5381 05 Aug 10 nicklas 229   */
5381 05 Aug 10 nicklas 230   protected DynamicField getAdvancedReporterField(String expression, boolean required)
5381 05 Aug 10 nicklas 231   {
5381 05 Aug 10 nicklas 232     DynamicField df = null;
5381 05 Aug 10 nicklas 233     Pattern p = null;
5381 05 Aug 10 nicklas 234     Matcher m = null;
5381 05 Aug 10 nicklas 235     
5381 05 Aug 10 nicklas 236     // Check: =property("name", "title")
5381 05 Aug 10 nicklas 237     p = getPattern("property", 1, 1);  
5381 05 Aug 10 nicklas 238     m = p.matcher(expression);
5381 05 Aug 10 nicklas 239     if (m.matches())
5381 05 Aug 10 nicklas 240     {
5381 05 Aug 10 nicklas 241       String name = m.group(1);
5381 05 Aug 10 nicklas 242       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 243       df = getReporterProperty(name, title);
5381 05 Aug 10 nicklas 244       if (df == null && required) 
5381 05 Aug 10 nicklas 245       {
5381 05 Aug 10 nicklas 246         throw new ItemNotFoundException("Unknown reporter property in expression: " + expression);
5381 05 Aug 10 nicklas 247       }
5381 05 Aug 10 nicklas 248       return df;
5381 05 Aug 10 nicklas 249     }
5381 05 Aug 10 nicklas 250     
5381 05 Aug 10 nicklas 251     // Check: =formula("formula", "title")
5381 05 Aug 10 nicklas 252     p = getPattern("formula", 1, 1);
5381 05 Aug 10 nicklas 253     m = p.matcher(expression);
5381 05 Aug 10 nicklas 254     if (m.matches())
5381 05 Aug 10 nicklas 255     {
5381 05 Aug 10 nicklas 256       String name = m.group(1);
5381 05 Aug 10 nicklas 257       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 258       df = getFormulaField(name, title);
5381 05 Aug 10 nicklas 259       if (df == null && required) 
5381 05 Aug 10 nicklas 260       {
5381 05 Aug 10 nicklas 261         throw new ItemNotFoundException("Unknown formula in expression: " + expression);
5381 05 Aug 10 nicklas 262       }
5381 05 Aug 10 nicklas 263       return df;
5381 05 Aug 10 nicklas 264     }
5381 05 Aug 10 nicklas 265
5381 05 Aug 10 nicklas 266     // Check: =xtra("name", "title")
5381 05 Aug 10 nicklas 267     p = getPattern("xtra", 1, 1);
5381 05 Aug 10 nicklas 268     m = p.matcher(expression);
5381 05 Aug 10 nicklas 269     if (m.matches())
5381 05 Aug 10 nicklas 270     {
5381 05 Aug 10 nicklas 271       String name = m.group(1);
5381 05 Aug 10 nicklas 272       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 273       df = getExtraValueField(name, CoordinateType.POSITION, title);
5381 05 Aug 10 nicklas 274       if (df == null && required) 
5381 05 Aug 10 nicklas 275       {
5381 05 Aug 10 nicklas 276         throw new ItemNotFoundException("Unknown extra value in expression: " + expression);
5381 05 Aug 10 nicklas 277       }
5381 05 Aug 10 nicklas 278       return df;
5381 05 Aug 10 nicklas 279     }
5381 05 Aug 10 nicklas 280
5381 05 Aug 10 nicklas 281     // Check: =jep("name", "title", "datatype")
5381 05 Aug 10 nicklas 282     p = getPattern("jep", 2, 1);
5381 05 Aug 10 nicklas 283     m = p.matcher(expression);
5381 05 Aug 10 nicklas 284     if (m.matches())
5381 05 Aug 10 nicklas 285     {
5381 05 Aug 10 nicklas 286       String jep = m.group(1);
5381 05 Aug 10 nicklas 287       String title = m.group(2);
5381 05 Aug 10 nicklas 288       String dataType = Values.getString(m.group(3), "STRING");
5381 05 Aug 10 nicklas 289       df = ExportableFieldFactory.jep(jep, title, Type.valueOf(dataType.toUpperCase()), null, null);
5381 05 Aug 10 nicklas 290       return df;
5381 05 Aug 10 nicklas 291     }
5381 05 Aug 10 nicklas 292
5381 05 Aug 10 nicklas 293     if (df == null && required)
5381 05 Aug 10 nicklas 294     {
5381 05 Aug 10 nicklas 295       throw new InvalidDataException("Invalid reporter field expression: " + expression);
5381 05 Aug 10 nicklas 296     }
5381 05 Aug 10 nicklas 297     
5381 05 Aug 10 nicklas 298     return df;
5381 05 Aug 10 nicklas 299   }
5381 05 Aug 10 nicklas 300   
5381 05 Aug 10 nicklas 301   /**
5381 05 Aug 10 nicklas 302     Convert an expression to a spot field. Supported expressions are
5381 05 Aug 10 nicklas 303     listed below. The "title" parameter is optional in the "jep" expression.
5381 05 Aug 10 nicklas 304     <ul>
5381 05 Aug 10 nicklas 305     <li>=property("name" [,"title"]): Get the value of the raw data property 
5381 05 Aug 10 nicklas 306       with the given name.
5381 05 Aug 10 nicklas 307     <li>=formula("name" [,"title"]): Get the value of the formula 
5381 05 Aug 10 nicklas 308       with the given name. The formula should only use
5381 05 Aug 10 nicklas 309       properties that are related to the spot and raw data.
5381 05 Aug 10 nicklas 310     <li>=xtra("name" [,"title"]): Get the value of the extra value with
5381 05 Aug 10 nicklas 311       the given name or external id. The extra value should be a 
5381 05 Aug 10 nicklas 312       spot-based extra value.
5381 05 Aug 10 nicklas 313     <li>=jep("expression", "title" [,"datatype"]): Calculate the value using the
5381 05 Aug 10 nicklas 314       given JEP expression. A title is required. The datatype is optional
5381 05 Aug 10 nicklas 315       (default is STRING). Valid datatypes are those defined by the
5381 05 Aug 10 nicklas 316       {@link Type} enumeration.
5381 05 Aug 10 nicklas 317     </ul>
5381 05 Aug 10 nicklas 318   */
5381 05 Aug 10 nicklas 319   protected DynamicField getAdvancedSpotField(String expression, boolean required)
5381 05 Aug 10 nicklas 320   {
5381 05 Aug 10 nicklas 321     DynamicField df = null;
5381 05 Aug 10 nicklas 322     Pattern p = null;
5381 05 Aug 10 nicklas 323     Matcher m = null;
5381 05 Aug 10 nicklas 324     
5381 05 Aug 10 nicklas 325     // Check: =property("name", "title")
5381 05 Aug 10 nicklas 326     p = getPattern("property", 1, 1);  
5381 05 Aug 10 nicklas 327     m = p.matcher(expression);
5381 05 Aug 10 nicklas 328     if (m.matches())
5381 05 Aug 10 nicklas 329     {
5381 05 Aug 10 nicklas 330       String name = m.group(1);
5381 05 Aug 10 nicklas 331       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 332       df = getRawDataProperty(name, title);
5381 05 Aug 10 nicklas 333       if (df == null && required) 
5381 05 Aug 10 nicklas 334       {
5381 05 Aug 10 nicklas 335         throw new ItemNotFoundException("Unknown raw data property in expression: " + expression);
5381 05 Aug 10 nicklas 336       }
5381 05 Aug 10 nicklas 337       return df;
5381 05 Aug 10 nicklas 338     }
5381 05 Aug 10 nicklas 339     
5381 05 Aug 10 nicklas 340     // Check: =formula("formula", "title")
5381 05 Aug 10 nicklas 341     p = getPattern("formula", 1, 1);
5381 05 Aug 10 nicklas 342     m = p.matcher(expression);
5381 05 Aug 10 nicklas 343     if (m.matches())
5381 05 Aug 10 nicklas 344     {
5381 05 Aug 10 nicklas 345       String name = m.group(1);
5381 05 Aug 10 nicklas 346       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 347       df = getFormulaField(name, title);
5381 05 Aug 10 nicklas 348       if (df == null && required) 
5381 05 Aug 10 nicklas 349       {
5381 05 Aug 10 nicklas 350         throw new ItemNotFoundException("Unknown formula in expression: " + expression);
5381 05 Aug 10 nicklas 351       }
5381 05 Aug 10 nicklas 352       return df;
5381 05 Aug 10 nicklas 353     }
5381 05 Aug 10 nicklas 354     
5381 05 Aug 10 nicklas 355     // Check: =xtra("name", "title")
5381 05 Aug 10 nicklas 356     p = getPattern("xtra", 1, 1);
5381 05 Aug 10 nicklas 357     m = p.matcher(expression);
5381 05 Aug 10 nicklas 358     if (m.matches())
5381 05 Aug 10 nicklas 359     {
5381 05 Aug 10 nicklas 360       String name = m.group(1);
5381 05 Aug 10 nicklas 361       String title = Values.getString(m.group(2), name);
5381 05 Aug 10 nicklas 362       df = getExtraValueField(name, CoordinateType.SPOT, title);
5381 05 Aug 10 nicklas 363       if (df == null && required) 
5381 05 Aug 10 nicklas 364       {
5381 05 Aug 10 nicklas 365         throw new ItemNotFoundException("Unknown extra value in expression: " + expression);
5381 05 Aug 10 nicklas 366       }
5381 05 Aug 10 nicklas 367       return df;
5381 05 Aug 10 nicklas 368     }
5381 05 Aug 10 nicklas 369     
5381 05 Aug 10 nicklas 370     // Check: =jep("name", "title", "datatype")
5381 05 Aug 10 nicklas 371     p = getPattern("jep", 2, 1);
5381 05 Aug 10 nicklas 372     m = p.matcher(expression);
5381 05 Aug 10 nicklas 373     if (m.matches())
5381 05 Aug 10 nicklas 374     {
5381 05 Aug 10 nicklas 375       String jep = m.group(1);
5381 05 Aug 10 nicklas 376       String title = m.group(2);
5381 05 Aug 10 nicklas 377       String dataType = Values.getString(m.group(3), "STRING");
5381 05 Aug 10 nicklas 378       df = ExportableFieldFactory.jep(jep, title, Type.valueOf(dataType.toUpperCase()), null, null);
5381 05 Aug 10 nicklas 379       return df;
5381 05 Aug 10 nicklas 380     }
5381 05 Aug 10 nicklas 381     
5381 05 Aug 10 nicklas 382     if (df == null && required)
5381 05 Aug 10 nicklas 383     {
5381 05 Aug 10 nicklas 384       throw new InvalidDataException("Invalid reporter field expression: " + expression);
5381 05 Aug 10 nicklas 385     }
5381 05 Aug 10 nicklas 386     return df;
5381 05 Aug 10 nicklas 387   }
5381 05 Aug 10 nicklas 388
5381 05 Aug 10 nicklas 389   
5381 05 Aug 10 nicklas 390   private Pattern getPattern(String function, int requiredParameters, int optionalParameters)
5381 05 Aug 10 nicklas 391   {
5381 05 Aug 10 nicklas 392     Pattern p = patterns.get(function);
5381 05 Aug 10 nicklas 393     if (p == null)
5381 05 Aug 10 nicklas 394     {
5381 05 Aug 10 nicklas 395       StringBuilder sb = new StringBuilder();
5381 05 Aug 10 nicklas 396       sb.append("\\=").append(function).append("\\("); // matches: =function(
5381 05 Aug 10 nicklas 397       for (int i = 0; i < requiredParameters; ++i)
5381 05 Aug 10 nicklas 398       {
5381 05 Aug 10 nicklas 399         if (i > 0) sb.append(","); // matches: ,
5381 05 Aug 10 nicklas 400         sb.append("\\s*\\\"(.*?)\\\"\\s*");  // matches: "...."
5381 05 Aug 10 nicklas 401       }
5381 05 Aug 10 nicklas 402       for (int i = 0; i < optionalParameters; ++i)
5381 05 Aug 10 nicklas 403       {
5381 05 Aug 10 nicklas 404         sb.append("(?:,\\s*\\\"(.*?)\\\"\\s*)?");
5381 05 Aug 10 nicklas 405       }
5381 05 Aug 10 nicklas 406       sb.append("\\)\\s*"); // matches: )
5381 05 Aug 10 nicklas 407       p = Pattern.compile(sb.toString());
5381 05 Aug 10 nicklas 408       patterns.put(function, p);
5381 05 Aug 10 nicklas 409     }
5381 05 Aug 10 nicklas 410     return p;
5381 05 Aug 10 nicklas 411   }
5381 05 Aug 10 nicklas 412 }