extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/cmd/PatternValidator.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
6201 09 Apr 21 nicklas 8
6200 08 Apr 21 nicklas 9 /**
6200 08 Apr 21 nicklas 10   Validator for string values that are expected to match a 
6200 08 Apr 21 nicklas 11   specific patter. If the value matches it is returned unmodified
6200 08 Apr 21 nicklas 12   or using the replacement template.
6200 08 Apr 21 nicklas 13
6200 08 Apr 21 nicklas 14   @since 4.32
6200 08 Apr 21 nicklas 15 */
6200 08 Apr 21 nicklas 16 public class PatternValidator
6200 08 Apr 21 nicklas 17   implements ValueValidator<String, String>
6200 08 Apr 21 nicklas 18 {
6200 08 Apr 21 nicklas 19   /**
6510 03 Dec 21 nicklas 20     A CMD ID is expected to be string with numbers and hyphen. We
6510 03 Dec 21 nicklas 21     add 'cmd:' prefix to the value.
6200 08 Apr 21 nicklas 22   */
6201 09 Apr 21 nicklas 23   public static final PatternValidator CMD_ID = new PatternValidator("[0-9]+[0-9\\-]+", "ID", "cmd:$0", null);
6200 08 Apr 21 nicklas 24
6201 09 Apr 21 nicklas 25   /**
6510 03 Dec 21 nicklas 26     A CMD Protocol. We allow any text, but add 'cmd:' prefix.
6510 03 Dec 21 nicklas 27   */
6710 27 Apr 22 nicklas 28   public static final PatternValidator CMD_PROTOCOL = new PatternValidator(".+", "protocol", "cmd:$0", null);
6510 03 Dec 21 nicklas 29   
6510 03 Dec 21 nicklas 30   /**
6510 03 Dec 21 nicklas 31     A Clarity ID is expected to be string with numbers and letters.
6510 03 Dec 21 nicklas 32   */
6710 27 Apr 22 nicklas 33   public static final PatternValidator CLARITY_ID = new PatternValidator("[A-Z0-9]+", "Clarity ID", "cmd:$0", null);
6710 27 Apr 22 nicklas 34
6510 03 Dec 21 nicklas 35   /**
6709 27 Apr 22 nicklas 36     A Specimen-ID is expected to be Clarity ID followed by a '-' and some letters.
6709 27 Apr 22 nicklas 37     @since 4.39
6709 27 Apr 22 nicklas 38   */
6709 27 Apr 22 nicklas 39   public static final PatternValidator SPECIMEN_ID = new PatternValidator("[A-Z0-9]+(\\-[A-Za-z]+)?", "Specimen-ID", null, null);
6709 27 Apr 22 nicklas 40
6709 27 Apr 22 nicklas 41   /**
6201 09 Apr 21 nicklas 42     A flow cell ID is uppercase letters and numbers. Typically
6201 09 Apr 21 nicklas 43     they are 9 characaters, but we allow between 6 and 12.
6201 09 Apr 21 nicklas 44   */
6201 09 Apr 21 nicklas 45   public static final PatternValidator FLOWCELL_ID = new PatternValidator("[A-Z0-9]{6,12}", "flow cell ID", null, "6-12 characters A-Z or 0-9");
6201 09 Apr 21 nicklas 46   
6201 09 Apr 21 nicklas 47   /**
6201 09 Apr 21 nicklas 48     The flow cell position is "A" or "B".
6201 09 Apr 21 nicklas 49   */
6201 09 Apr 21 nicklas 50   public static final PatternValidator SEQUENCER_POSITION = new PatternValidator("A|B", "flow cell position", null, "A or B");
6201 09 Apr 21 nicklas 51   
6201 09 Apr 21 nicklas 52   /**
6201 09 Apr 21 nicklas 53     Serial numbers are uppercase letters and numbers. Typically
6201 09 Apr 21 nicklas 54     5-10 characters but we allow between 2 and 20.
6201 09 Apr 21 nicklas 55   */
6201 09 Apr 21 nicklas 56   public static final PatternValidator SERIAL_NO = new PatternValidator("[A-Z0-9]{2,20}", "serial number", null, "2-20 characters A-Z or 0-9");
6203 09 Apr 21 nicklas 57
6203 09 Apr 21 nicklas 58   /**
6203 09 Apr 21 nicklas 59     At least four groups of [0-9]+[TBS].
6203 09 Apr 21 nicklas 60   */
6203 09 Apr 21 nicklas 61   public static final PatternValidator READ_STRING = new PatternValidator("([0-9]+[TBS]){4,8}", "read string", null, "at least 4 groups of [0-9]+[TBS]");
6203 09 Apr 21 nicklas 62
6209 13 Apr 21 nicklas 63   /**
6209 13 Apr 21 nicklas 64     4 groups of digits with - separator.
6209 13 Apr 21 nicklas 65   */
6209 13 Apr 21 nicklas 66   public static final PatternValidator SEQUENCING_CYCLES = new PatternValidator("([0-9]+\\-){3}[0-9]+", "sequencing cycles", null, "4 groups of 0-9");
6201 09 Apr 21 nicklas 67   
6217 19 Apr 21 nicklas 68   /**
6217 19 Apr 21 nicklas 69     PAD is uppercase letters and numbers or '-'. Typically 5-10
7286 15 Aug 23 nicklas 70     characters but we allow between 4 and 50 and issue a warning if
7286 15 Aug 23 nicklas 71     longer 20.
6217 19 Apr 21 nicklas 72   */
7286 15 Aug 23 nicklas 73   public static final PatternValidator PAD = new PatternValidator("[A-Z0-9-]{4,50}", "PAD", null, "4-20/50 characters A-Z, 0-9 or '-'").warnIfLonger(20);
6217 19 Apr 21 nicklas 74   
6221 23 Apr 21 nicklas 75   /**
6221 23 Apr 21 nicklas 76     Filenames are allowed to have A-Z (upper and lower case), 0-9, '-', '_', and '.'.
6221 23 Apr 21 nicklas 77   */
6221 23 Apr 21 nicklas 78   public static final PatternValidator FILE_NAME = new PatternValidator("[a-zA-Z0-9_.-]+", "file name", null, "A-Z, 0-9, '-', '_' or '.'");
6221 23 Apr 21 nicklas 79   
6221 23 Apr 21 nicklas 80   /**
6221 23 Apr 21 nicklas 81     MD5 validator.
6221 23 Apr 21 nicklas 82   */
6221 23 Apr 21 nicklas 83   public static final PatternValidator MD5 = new PatternValidator("[a-f0-9]{32}", "MD5", null, "32 characters, 0-9 or a-f");
6221 23 Apr 21 nicklas 84   
6200 08 Apr 21 nicklas 85   private final Pattern pattern;
6200 08 Apr 21 nicklas 86   private final String subject;
6200 08 Apr 21 nicklas 87   private final String replacement;
6201 09 Apr 21 nicklas 88   private final String expected;
6709 27 Apr 22 nicklas 89   private final String prefix;
6709 27 Apr 22 nicklas 90   private final String suffix;
7286 15 Aug 23 nicklas 91   private final Integer warnIfLonger;
6200 08 Apr 21 nicklas 92   
6201 09 Apr 21 nicklas 93   public PatternValidator(String pattern, String subject, String replacement, String expected)
6200 08 Apr 21 nicklas 94   {
6200 08 Apr 21 nicklas 95     this.pattern = Pattern.compile(pattern);
6200 08 Apr 21 nicklas 96     this.subject = subject;
6200 08 Apr 21 nicklas 97     this.replacement = replacement;
6201 09 Apr 21 nicklas 98     this.expected = expected;
6709 27 Apr 22 nicklas 99     this.prefix = null;
6709 27 Apr 22 nicklas 100     this.suffix = null;
7286 15 Aug 23 nicklas 101     this.warnIfLonger = null;
6200 08 Apr 21 nicklas 102   }
6200 08 Apr 21 nicklas 103   
7286 15 Aug 23 nicklas 104   private PatternValidator(PatternValidator parent, int warnIfLonger)
7286 15 Aug 23 nicklas 105   {
7286 15 Aug 23 nicklas 106     this.pattern = parent.pattern;
7286 15 Aug 23 nicklas 107     this.subject = parent.subject;
7286 15 Aug 23 nicklas 108     this.replacement = parent.replacement;
7286 15 Aug 23 nicklas 109     this.expected = parent.expected;
7286 15 Aug 23 nicklas 110     this.prefix = null;
7286 15 Aug 23 nicklas 111     this.suffix = null;
7286 15 Aug 23 nicklas 112     this.warnIfLonger = warnIfLonger;
7286 15 Aug 23 nicklas 113   }
7286 15 Aug 23 nicklas 114   
6709 27 Apr 22 nicklas 115   private PatternValidator(PatternValidator parent, String prefix, String suffix)
6709 27 Apr 22 nicklas 116   {
6709 27 Apr 22 nicklas 117     this.pattern = parent.pattern;
6709 27 Apr 22 nicklas 118     this.subject = parent.subject;
6709 27 Apr 22 nicklas 119     this.replacement = parent.replacement;
6709 27 Apr 22 nicklas 120     this.expected = parent.expected;
6709 27 Apr 22 nicklas 121     this.prefix = prefix;
6709 27 Apr 22 nicklas 122     this.suffix = suffix;
7286 15 Aug 23 nicklas 123     this.warnIfLonger = null;
6709 27 Apr 22 nicklas 124   }
6709 27 Apr 22 nicklas 125
6200 08 Apr 21 nicklas 126   @Override
6201 09 Apr 21 nicklas 127   public String isValid(DbControl dc, String value, JsonSection section, String entryKey)
6200 08 Apr 21 nicklas 128   {
6221 23 Apr 21 nicklas 129     if (value != null)
6200 08 Apr 21 nicklas 130     {
6221 23 Apr 21 nicklas 131       Matcher m = pattern.matcher(value);
6221 23 Apr 21 nicklas 132       if (!m.matches())
6221 23 Apr 21 nicklas 133       {
6221 23 Apr 21 nicklas 134         section.addErrorMessage("Invalid "+subject+" in JSON: "+entryKey+"="+value+(expected!=null?" (expected " +expected+")":""));
6221 23 Apr 21 nicklas 135         return null;
6221 23 Apr 21 nicklas 136       }
6709 27 Apr 22 nicklas 137       if (prefix != null && !value.startsWith(prefix))
6709 27 Apr 22 nicklas 138       {
6709 27 Apr 22 nicklas 139         section.addWarningMessage("Unexpected prefix: "+entryKey+"="+value+" (expected '"+prefix+"')");
6709 27 Apr 22 nicklas 140       }
6709 27 Apr 22 nicklas 141       if (suffix != null && !value.endsWith(suffix))
6709 27 Apr 22 nicklas 142       {
6709 27 Apr 22 nicklas 143         section.addWarningMessage("Unexpected suffix: "+entryKey+"="+value+" (expected '"+suffix+"')");
6709 27 Apr 22 nicklas 144       }
7286 15 Aug 23 nicklas 145       if (warnIfLonger != null && value.length() > warnIfLonger)
7286 15 Aug 23 nicklas 146       {
7286 15 Aug 23 nicklas 147         section.addWarningMessage("Long "+subject+" in JSON: "+entryKey+"="+value+" (expected <= " +warnIfLonger+" characters)");
7286 15 Aug 23 nicklas 148       }
6221 23 Apr 21 nicklas 149       if (replacement != null) value = m.replaceAll(replacement);
6200 08 Apr 21 nicklas 150     }
6200 08 Apr 21 nicklas 151     return value;
6200 08 Apr 21 nicklas 152   }
6200 08 Apr 21 nicklas 153   
6200 08 Apr 21 nicklas 154   @Override
6200 08 Apr 21 nicklas 155   public Class<String> getExpectedClass() 
6200 08 Apr 21 nicklas 156   {
6200 08 Apr 21 nicklas 157     return String.class;
6200 08 Apr 21 nicklas 158   }
6709 27 Apr 22 nicklas 159   
6710 27 Apr 22 nicklas 160   /**
6993 20 Jan 23 nicklas 161     A simple check if the given value matches the pattern. No errors
6993 20 Jan 23 nicklas 162     are reported.
6993 20 Jan 23 nicklas 163   */
6993 20 Jan 23 nicklas 164   public boolean matches(String value)
6993 20 Jan 23 nicklas 165   {
6993 20 Jan 23 nicklas 166     return value != null && pattern.matcher(value).matches();
6993 20 Jan 23 nicklas 167   }
6993 20 Jan 23 nicklas 168   
6993 20 Jan 23 nicklas 169   /**
6710 27 Apr 22 nicklas 170     Wrap this validator in a validator that also checks the if value 
6710 27 Apr 22 nicklas 171     starts and/or ends with the given prefix and suffix. Warning-level
6710 27 Apr 22 nicklas 172     messages are created if the value doesn't match. Use null for the 
6710 27 Apr 22 nicklas 173     prefix or suffix to skip the check.
6710 27 Apr 22 nicklas 174     @since 4.39
6710 27 Apr 22 nicklas 175   */
6709 27 Apr 22 nicklas 176   public PatternValidator withPrefixSuffix(String prefix, String suffix)
6709 27 Apr 22 nicklas 177   {
6709 27 Apr 22 nicklas 178     return new PatternValidator(this, prefix, suffix);
6709 27 Apr 22 nicklas 179   }
7286 15 Aug 23 nicklas 180   
7286 15 Aug 23 nicklas 181   /**
7286 15 Aug 23 nicklas 182     Wrap this validator in a validator that also checks the length of
7286 15 Aug 23 nicklas 183     the value and issues a warning if it is longer than the given
7286 15 Aug 23 nicklas 184     max length.
7286 15 Aug 23 nicklas 185     @since 4.48.5
7286 15 Aug 23 nicklas 186   */
7286 15 Aug 23 nicklas 187   public PatternValidator warnIfLonger(int maxLength)
7286 15 Aug 23 nicklas 188   {
7286 15 Aug 23 nicklas 189     return new PatternValidator(this, maxLength);
7286 15 Aug 23 nicklas 190   }
6200 08 Apr 21 nicklas 191
6200 08 Apr 21 nicklas 192 }