extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/PlateWellValidator.java

Code
Comments
Other
Rev Date Author Line
6200 08 Apr 21 nicklas 1 package net.sf.basedb.reggie.plugins.cmd;
6200 08 Apr 21 nicklas 2
6200 08 Apr 21 nicklas 3 import java.util.regex.Matcher;
6200 08 Apr 21 nicklas 4 import java.util.regex.Pattern;
6200 08 Apr 21 nicklas 5
6201 09 Apr 21 nicklas 6 import net.sf.basedb.core.DbControl;
6200 08 Apr 21 nicklas 7 import net.sf.basedb.core.data.PlateCoordinate;
6474 04 Nov 21 nicklas 8 import net.sf.basedb.util.Coordinate;
6200 08 Apr 21 nicklas 9
6200 08 Apr 21 nicklas 10 /**
6200 08 Apr 21 nicklas 11   Validator for plate well coordinates that are expected to
6200 08 Apr 21 nicklas 12   be strings in the format "row:column", where 'row' and 'column'
6474 04 Nov 21 nicklas 13   are either A1B1-style or 1-based integer values up to a specified 
6474 04 Nov 21 nicklas 14   max number of rows/columns. If the coordinates are valid they are 
6474 04 Nov 21 nicklas 15   converted to 0-bases and returned as a PlateCoordinate instance. 
6200 08 Apr 21 nicklas 16   
6200 08 Apr 21 nicklas 17   @since 4.32
6200 08 Apr 21 nicklas 18 */
6200 08 Apr 21 nicklas 19 public class PlateWellValidator
6200 08 Apr 21 nicklas 20   implements ValueValidator<String, PlateCoordinate>
6200 08 Apr 21 nicklas 21 {
6200 08 Apr 21 nicklas 22   
6200 08 Apr 21 nicklas 23   /**
6200 08 Apr 21 nicklas 24     Validator for plates with 8 rows and 12 columns.
6200 08 Apr 21 nicklas 25   */
6510 03 Dec 21 nicklas 26   public static final PlateWellValidator PLATE_8x12 = new PlateWellValidator(8, 12, CoordinateSystem.ALPHA_NUMERIC);
6207 12 Apr 21 nicklas 27   
6207 12 Apr 21 nicklas 28   /**
6474 04 Nov 21 nicklas 29     Validator for strips with 1 row and 8 columns.
6474 04 Nov 21 nicklas 30     @since 4.33.4
6474 04 Nov 21 nicklas 31   */
6510 03 Dec 21 nicklas 32   public static final PlateWellValidator STRIP_1x8 = new PlateWellValidator(1, 8, CoordinateSystem.NUMERIC);
6474 04 Nov 21 nicklas 33   
6474 04 Nov 21 nicklas 34   /**
6207 12 Apr 21 nicklas 35     Validator fow Qiacube positions which are represented as 6 rows with 2 columns.
6207 12 Apr 21 nicklas 36   */
6510 03 Dec 21 nicklas 37   public static final PlateWellValidator QIACUBE = new PlateWellValidator(6, 2, CoordinateSystem.NUMERIC_ALPHA);
6200 08 Apr 21 nicklas 38
6200 08 Apr 21 nicklas 39   private final int maxRows;
6200 08 Apr 21 nicklas 40   private final int maxCols;
6510 03 Dec 21 nicklas 41   private final CoordinateSystem[] systems;
6200 08 Apr 21 nicklas 42   
6510 03 Dec 21 nicklas 43   public PlateWellValidator(int maxRows, int maxCols, CoordinateSystem... systems)
6200 08 Apr 21 nicklas 44   {
6200 08 Apr 21 nicklas 45     this.maxRows = maxRows;
6200 08 Apr 21 nicklas 46     this.maxCols = maxCols;
6510 03 Dec 21 nicklas 47     this.systems = systems;
6200 08 Apr 21 nicklas 48   }
6200 08 Apr 21 nicklas 49   
6200 08 Apr 21 nicklas 50   @Override
6201 09 Apr 21 nicklas 51   public PlateCoordinate isValid(DbControl dc, String value, JsonSection section, String entryKey)
6200 08 Apr 21 nicklas 52   {
6510 03 Dec 21 nicklas 53     
6510 03 Dec 21 nicklas 54     for (CoordinateSystem cs : systems)
6200 08 Apr 21 nicklas 55     {
6510 03 Dec 21 nicklas 56       Matcher m = cs.matcher(value);
6510 03 Dec 21 nicklas 57       if (m.matches())
6474 04 Nov 21 nicklas 58       {
6510 03 Dec 21 nicklas 59         int row = cs.getRow(m);
6510 03 Dec 21 nicklas 60         int col = cs.getCol(m);
6510 03 Dec 21 nicklas 61         boolean valid = true;
6510 03 Dec 21 nicklas 62         
6510 03 Dec 21 nicklas 63         if (row < 1)
6510 03 Dec 21 nicklas 64         {
6510 03 Dec 21 nicklas 65           section.addErrorMessage("Row coordinate <"+cs.row(1)+" in JSON: "+entryKey+"="+value);
6510 03 Dec 21 nicklas 66           valid = false;
6510 03 Dec 21 nicklas 67         }
6510 03 Dec 21 nicklas 68         else if (row > maxRows)
6510 03 Dec 21 nicklas 69         {
6510 03 Dec 21 nicklas 70           section.addErrorMessage("Row coordinate >"+cs.row(maxRows)+" in JSON: "+entryKey+"="+value);
6510 03 Dec 21 nicklas 71           valid = false;
6510 03 Dec 21 nicklas 72         }
6510 03 Dec 21 nicklas 73         if (col < 1)
6510 03 Dec 21 nicklas 74         {
6510 03 Dec 21 nicklas 75           section.addErrorMessage("Column coordinate <"+cs.col(1)+" in JSON: "+entryKey+"="+value);
6510 03 Dec 21 nicklas 76           valid = false;
6510 03 Dec 21 nicklas 77         }
6510 03 Dec 21 nicklas 78         else if (col > maxCols)
6510 03 Dec 21 nicklas 79         {
6510 03 Dec 21 nicklas 80           section.addErrorMessage("Column coordinate >"+cs.col(maxCols)+" in JSON: "+entryKey+"="+value);
6510 03 Dec 21 nicklas 81           valid = false;
6510 03 Dec 21 nicklas 82         }
6510 03 Dec 21 nicklas 83         
6510 03 Dec 21 nicklas 84         return valid ? new PlateCoordinate(row-1, col-1) : null; 
6474 04 Nov 21 nicklas 85       }
6200 08 Apr 21 nicklas 86     }
6200 08 Apr 21 nicklas 87     
6510 03 Dec 21 nicklas 88     section.addErrorMessage("Invalid plate well in JSON: "+entryKey+"="+value);
6510 03 Dec 21 nicklas 89     return null;
6200 08 Apr 21 nicklas 90   }
6200 08 Apr 21 nicklas 91   
6200 08 Apr 21 nicklas 92   @Override
6200 08 Apr 21 nicklas 93   public Class<String> getExpectedClass() 
6200 08 Apr 21 nicklas 94   {
6200 08 Apr 21 nicklas 95     return String.class;
6200 08 Apr 21 nicklas 96   }
6200 08 Apr 21 nicklas 97
6510 03 Dec 21 nicklas 98   /**
6510 03 Dec 21 nicklas 99     Handles variations in coordinate systems.
6510 03 Dec 21 nicklas 100     @since 4.33.5
6510 03 Dec 21 nicklas 101   */
6510 03 Dec 21 nicklas 102   static enum CoordinateSystem
6510 03 Dec 21 nicklas 103   {
6510 03 Dec 21 nicklas 104     /**
6510 03 Dec 21 nicklas 105       Both coordinates are numeric. Eg. 1:1, 2:1
6510 03 Dec 21 nicklas 106      */
6510 03 Dec 21 nicklas 107     NUMERIC(Pattern.compile("(\\d+)\\:(\\d+)"), false, false),
6510 03 Dec 21 nicklas 108     /**
6510 03 Dec 21 nicklas 109       The first (row) coordinate is alphabetic: A:1, B:2, etc.
6510 03 Dec 21 nicklas 110     */
6510 03 Dec 21 nicklas 111     ALPHA_NUMERIC(Pattern.compile("([A-Z]+)\\:(\\d+)"), true, false),
6510 03 Dec 21 nicklas 112     /**
6510 03 Dec 21 nicklas 113       The second (column) coordinate is alphabetic: 1:A, 2:B, etc.
6510 03 Dec 21 nicklas 114     */
6510 03 Dec 21 nicklas 115     NUMERIC_ALPHA(Pattern.compile("(\\d+)\\:([A-Z]+)"), false, true);
6510 03 Dec 21 nicklas 116     
6510 03 Dec 21 nicklas 117     private final Pattern p;
6510 03 Dec 21 nicklas 118     private final boolean rowAlpha;
6510 03 Dec 21 nicklas 119     private final boolean colAlpha;
6510 03 Dec 21 nicklas 120     
6510 03 Dec 21 nicklas 121     private CoordinateSystem(Pattern p, boolean rowAlpha, boolean colAlpha)
6510 03 Dec 21 nicklas 122     {
6510 03 Dec 21 nicklas 123       this.p = p;
6510 03 Dec 21 nicklas 124       this.rowAlpha = rowAlpha;
6510 03 Dec 21 nicklas 125       this.colAlpha = colAlpha;
6510 03 Dec 21 nicklas 126     }
6510 03 Dec 21 nicklas 127     
6510 03 Dec 21 nicklas 128     Matcher matcher(String value)
6510 03 Dec 21 nicklas 129     {
6510 03 Dec 21 nicklas 130       return p.matcher(value);
6510 03 Dec 21 nicklas 131     }
6510 03 Dec 21 nicklas 132     
6510 03 Dec 21 nicklas 133     int getRow(Matcher m)
6510 03 Dec 21 nicklas 134     {
6510 03 Dec 21 nicklas 135       String r = m.group(1);
6510 03 Dec 21 nicklas 136       return rowAlpha ? Coordinate.alphaToNumeric(r) : Integer.parseInt(r);
6510 03 Dec 21 nicklas 137     }
6510 03 Dec 21 nicklas 138
6510 03 Dec 21 nicklas 139     int getCol(Matcher m)
6510 03 Dec 21 nicklas 140     {
6510 03 Dec 21 nicklas 141       String c = m.group(2);
6510 03 Dec 21 nicklas 142       return colAlpha ? Coordinate.alphaToNumeric(c) : Integer.parseInt(c);
6510 03 Dec 21 nicklas 143     }
6510 03 Dec 21 nicklas 144
6510 03 Dec 21 nicklas 145     String row(int row)
6510 03 Dec 21 nicklas 146     {
6510 03 Dec 21 nicklas 147       return rowAlpha ? Coordinate.numericToAlpha(row) : Integer.toString(row);
6510 03 Dec 21 nicklas 148     }
6510 03 Dec 21 nicklas 149     
6510 03 Dec 21 nicklas 150     String col(int col)
6510 03 Dec 21 nicklas 151     {
6510 03 Dec 21 nicklas 152       return colAlpha ? Coordinate.numericToAlpha(col) : Integer.toString(col);
6510 03 Dec 21 nicklas 153     }
6510 03 Dec 21 nicklas 154   }
6200 08 Apr 21 nicklas 155 }