001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.view.TableView; 016 017import java.math.BigInteger; 018import java.util.HashMap; 019import java.util.List; 020import java.util.StringTokenizer; 021 022import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; 023import org.eclipse.nebula.widgets.nattable.data.validate.DataValidator; 024import org.eclipse.nebula.widgets.nattable.data.validate.ValidationFailedException; 025import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; 026 027import hdf.hdf5lib.HDF5Constants; 028import hdf.object.CompoundDataFormat; 029import hdf.object.DataFormat; 030import hdf.object.Datatype; 031import hdf.object.h5.H5Datatype; 032 033/** 034 * A Factory class to return a DataValidator class for a NatTable instance based 035 * upon the Datatype that it is supplied. 036 * 037 * @author Jordan T. Henderson 038 * @version 1.0 6/28/2018 039 * 040 */ 041public class DataValidatorFactory { 042 043 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DataValidatorFactory.class); 044 045 /* 046 * To keep things clean from an API perspective, keep a static reference to the 047 * last CompoundDataFormat that was passed in. This keeps us from needing to 048 * pass the CompoundDataFormat object as a parameter to every DataValidator 049 * class, since it's really only needed by the CompoundDataValidator. 050 */ 051 private static DataFormat dataFormatReference = null; 052 053 public static HDFDataValidator getDataValidator(final DataFormat dataObject) throws Exception { 054 if (dataObject == null) { 055 log.debug("getDataValidator(DataFormat): data object is null"); 056 throw new Exception("Must supply a valid DataFormat to the DataValidatorFactory"); 057 } 058 059 dataFormatReference = dataObject; 060 061 HDFDataValidator validator = null; 062 try { 063 validator = getDataValidator(dataObject.getDatatype()); 064 } 065 catch (Exception ex) { 066 log.debug("getDataValidator(DataFormat): failed to retrieve a DataValidator: ", ex); 067 validator = null; 068 } 069 070 /* 071 * By default, never validate if a proper DataValidator was not found. 072 */ 073 if (validator == null) { 074 log.debug("getDataValidator(DataFormat): using a default data validator"); 075 076 validator = new HDFDataValidator(dataObject.getDatatype()); 077 } 078 079 return validator; 080 } 081 082 private static HDFDataValidator getDataValidator(Datatype dtype) throws Exception { 083 HDFDataValidator validator = null; 084 085 try { 086 if (dtype.isCompound()) 087 validator = new CompoundDataValidator(dtype); 088 else if (dtype.isArray()) 089 validator = new ArrayDataValidator(dtype); 090 else if (dtype.isVLEN() && !dtype.isVarStr()) 091 validator = new VlenDataValidator(dtype); 092 else if (dtype.isString() || dtype.isVarStr()) 093 validator = new StringDataValidator(dtype); 094 else if (dtype.isChar()) 095 validator = new CharDataValidator(dtype); 096 else if (dtype.isInteger() || dtype.isFloat()) 097 validator = new NumericalDataValidator(dtype); 098 else if (dtype.isEnum()) 099 validator = new EnumDataValidator(dtype); 100 else if (dtype.isOpaque() || dtype.isBitField()) 101 validator = new BitfieldDataValidator(dtype); 102 else if (dtype.isRef()) 103 validator = new RefDataValidator(dtype); 104 } 105 catch (Exception ex) { 106 log.debug("getDataValidator(Datatype): failed to retrieve a DataValidator: ", ex); 107 validator = null; 108 } 109 110 /* 111 * By default, never validate if a proper DataValidator was not found. 112 */ 113 if (validator == null) { 114 log.debug("getDataValidator(Datatype): using a default data validator"); 115 116 validator = new HDFDataValidator(dtype); 117 } 118 119 return validator; 120 } 121 122 public static class HDFDataValidator extends DataValidator { 123 protected org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HDFDataValidator.class); 124 125 /* 126 * This field is only used for CompoundDataValidator, but when the top-level 127 * DataValidator is a "container" type, such as an ArrayDataValidator, we have 128 * to set this field and pass it through in case there is a 129 * CompoundDataValidator at the bottom of the chain. 130 */ 131 protected int cellColIdx; 132 133 HDFDataValidator(final Datatype dtype) { 134 cellColIdx = -1; 135 } 136 137 @Override 138 public boolean validate(int colIndex, int rowIndex, Object newValue) { 139 throwValidationFailedException(rowIndex, colIndex, newValue, 140 "A proper DataValidator wasn't found for this type of data. Writing this type of data will be disabled."); 141 142 return false; 143 } 144 145 protected void checkValidValue(Object newValue) throws ValidationFailedException { 146 if (newValue == null) 147 throw new ValidationFailedException("value is null"); 148 149 if (!(newValue instanceof String)) 150 throw new ValidationFailedException("value is not a String"); 151 } 152 153 protected void throwValidationFailedException(int rowIndex, int colIndex, Object newValue, String reason) 154 throws ValidationFailedException { 155 throw new ValidationFailedException("Failed to update value at " + "(" + rowIndex + ", " 156 + colIndex + ") to '" + newValue.toString() + "': " + reason); 157 } 158 } 159 160 /* 161 * NatTable DataValidator to validate entered input for a dataset with 162 * a Compound datatype by calling the appropriate validator on the member 163 * at the given row and column index. The correct validator is determined 164 * by taking the column index modulo the number of selected members in the 165 * Compound datatype, and grabbing the correct validator from the stored 166 * list of validators. 167 */ 168 private static class CompoundDataValidator extends HDFDataValidator { 169 private final HashMap<Integer, Integer> baseValidatorIndexMap; 170 private final HashMap<Integer, Integer> relCmpdStartIndexMap; 171 private final HDFDataValidator[] memberValidators; 172 private final int nTotFields; 173 174 CompoundDataValidator(final Datatype dtype) throws Exception { 175 super(dtype); 176 177 log = org.slf4j.LoggerFactory.getLogger(CompoundDataValidator.class); 178 179 if (!dtype.isCompound()) { 180 log.debug("datatype is not a compound type"); 181 throw new Exception("CompoundDataValidator: datatype is not a compound type"); 182 } 183 184 CompoundDataFormat compoundFormat = (CompoundDataFormat) dataFormatReference; 185 186 List<Datatype> localSelectedTypes = DataFactoryUtils.filterNonSelectedMembers(compoundFormat, dtype); 187 188 log.trace("setting up {} base HDFDataValidators", localSelectedTypes.size()); 189 190 memberValidators = new HDFDataValidator[localSelectedTypes.size()]; 191 for (int i = 0; i < memberValidators.length; i++) { 192 log.trace("retrieving DataValidator for member {}", i); 193 194 try { 195 memberValidators[i] = getDataValidator(localSelectedTypes.get(i)); 196 } 197 catch (Exception ex) { 198 log.debug("failed to retrieve DataValidator for member {}: ", i, ex); 199 memberValidators[i] = null; 200 } 201 } 202 203 /* 204 * Build necessary index maps. 205 */ 206 HashMap<Integer, Integer>[] maps = DataFactoryUtils.buildIndexMaps(compoundFormat, localSelectedTypes); 207 baseValidatorIndexMap = maps[DataFactoryUtils.COL_TO_BASE_CLASS_MAP_INDEX]; 208 relCmpdStartIndexMap = maps[DataFactoryUtils.CMPD_START_IDX_MAP_INDEX]; 209 210 log.trace("index maps built: baseValidatorIndexMap = {}, relColIdxMap = {}", 211 baseValidatorIndexMap.toString(), relCmpdStartIndexMap.toString()); 212 213 if (baseValidatorIndexMap.size() == 0) { 214 log.debug("base DataValidator index mapping is invalid - size 0"); 215 throw new Exception("CompoundDataValidator: invalid DataValidator mapping of size 0 built"); 216 } 217 218 if (relCmpdStartIndexMap.size() == 0) { 219 log.debug("compound field start index mapping is invalid - size 0"); 220 throw new Exception("CompoundDataValidator: invalid compound field start index mapping of size 0 built"); 221 } 222 223 nTotFields = baseValidatorIndexMap.size(); 224 } 225 226 @Override 227 public boolean validate(ILayerCell cell, IConfigRegistry configRegistry, Object newValue) { 228 cellColIdx = cell.getColumnIndex() % nTotFields; 229 return validate(cell.getColumnIndex(), cell.getRowIndex(), newValue); 230 } 231 232 @Override 233 public boolean validate(int colIndex, int rowIndex, Object newValue) { 234 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 235 236 try { 237 super.checkValidValue(newValue); 238 239 if (cellColIdx >= nTotFields) 240 cellColIdx %= nTotFields; 241 242 HDFDataValidator validator = memberValidators[baseValidatorIndexMap.get(cellColIdx)]; 243 validator.cellColIdx = cellColIdx - relCmpdStartIndexMap.get(cellColIdx); 244 245 validator.validate(colIndex, rowIndex, newValue); 246 } 247 catch (Exception ex) { 248 log.debug("validate({}, {}, {}): failed to validate: ", rowIndex, colIndex, newValue, ex); 249 throw new ValidationFailedException(ex.getMessage(), ex); 250 } 251 finally { 252 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 253 } 254 255 return true; 256 } 257 } 258 259 /* 260 * NatTable DataValidator to validate entered input for a dataset with 261 * an ARRAY datatype by calling the appropriate validator (as determined 262 * by the supplied datatype) on each of the array's elements. 263 */ 264 private static class ArrayDataValidator extends HDFDataValidator { 265 private final HDFDataValidator baseValidator; 266 267 ArrayDataValidator(final Datatype dtype) throws Exception { 268 super(dtype); 269 270 log = org.slf4j.LoggerFactory.getLogger(ArrayDataValidator.class); 271 272 if (!dtype.isArray()) { 273 log.debug("datatype is not an array type"); 274 throw new Exception("ArrayDataValidator: datatype is not an array type"); 275 } 276 277 Datatype baseType = dtype.getDatatypeBase(); 278 if (baseType == null) { 279 log.debug("base datatype is null"); 280 throw new Exception("ArrayDataValidator: base datatype is null"); 281 } 282 283 log.trace("ArrayDataValidator: base Datatype is {}", baseType.getDescription()); 284 285 try { 286 baseValidator = getDataValidator(baseType); 287 } 288 catch (Exception ex) { 289 log.debug("couldn't get DataValidator for base datatype: ", ex); 290 throw new Exception("ArrayDataValidator: couldn't get DataValidator for base datatype: " + ex.getMessage()); 291 } 292 } 293 294 @Override 295 public boolean validate(ILayerCell cell, IConfigRegistry configRegistry, Object newValue) { 296 cellColIdx = cell.getColumnIndex(); 297 return validate(cell.getColumnIndex(), cell.getRowIndex(), newValue); 298 } 299 300 @Override 301 public boolean validate(int colIndex, int rowIndex, Object newValue) { 302 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 303 304 try { 305 super.checkValidValue(newValue); 306 307 baseValidator.cellColIdx = cellColIdx; 308 309 StringTokenizer elementReader = new StringTokenizer((String) newValue, " \t\n\r\f,[]"); 310 while (elementReader.hasMoreTokens()) { 311 String nextToken = elementReader.nextToken(); 312 baseValidator.validate(colIndex, rowIndex, nextToken); 313 } 314 } 315 catch (Exception ex) { 316 log.debug("validate({}, {}, {}): failed to validate: ", rowIndex, colIndex, newValue, ex); 317 throw new ValidationFailedException(ex.getMessage(), ex); 318 } 319 finally { 320 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 321 } 322 323 return true; 324 } 325 } 326 327 /* 328 * NatTable DataValidator to validate entered input for a dataset with 329 * a variable-length Datatype (note that this DataValidator should not 330 * be used for String Datatypes that are variable-length). 331 */ 332 private static class VlenDataValidator extends HDFDataValidator { 333 private final HDFDataValidator baseValidator; 334 335 VlenDataValidator(Datatype dtype) throws Exception { 336 super(dtype); 337 338 log = org.slf4j.LoggerFactory.getLogger(VlenDataValidator.class); 339 340 if (!dtype.isVLEN() || dtype.isVarStr()) { 341 log.debug("datatype is not a variable-length type or is a variable-length string type (use StringDataValidator)"); 342 throw new Exception("VlenDataValidator: datatype is not a variable-length type or is a variable-length string type (use StringDataValidator)"); 343 } 344 345 Datatype baseType = dtype.getDatatypeBase(); 346 if (baseType == null) { 347 log.debug("base datatype is null"); 348 throw new Exception("VlenDataValidator: base datatype is null"); 349 } 350 351 log.trace("VlenDataValidator: base Datatype is {}", baseType.getDescription()); 352 353 try { 354 baseValidator = getDataValidator(baseType); 355 } 356 catch (Exception ex) { 357 log.debug("couldn't get DataValidator for base datatype: ", ex); 358 throw new Exception("VlenDataValidator: couldn't get DataValidator for base datatype: " + ex.getMessage()); 359 } 360 } 361 362 @Override 363 public boolean validate(ILayerCell cell, IConfigRegistry configRegistry, Object newValue) { 364 cellColIdx = cell.getColumnIndex(); 365 return validate(cell.getColumnIndex(), cell.getRowIndex(), newValue); 366 } 367 368 @Override 369 public boolean validate(int colIndex, int rowIndex, Object newValue) { 370 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 371 372 try { 373 super.checkValidValue(newValue); 374 375 baseValidator.cellColIdx = cellColIdx; 376 377 StringTokenizer elementReader = new StringTokenizer((String) newValue, " \t\n\r\f,()"); 378 while (elementReader.hasMoreTokens()) { 379 String nextToken = elementReader.nextToken(); 380 baseValidator.validate(colIndex, rowIndex, nextToken); 381 } 382 } 383 catch (Exception ex) { 384 log.debug("validate({}, {}, {}): failed to validate: ", rowIndex, colIndex, newValue, ex); 385 throw new ValidationFailedException(ex.getMessage(), ex); 386 } 387 finally { 388 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 389 } 390 391 return true; 392 } 393 } 394 395 /* 396 * NatTable DataValidator to validate entered input for a dataset with a String 397 * Datatype (including Strings of variable-length). 398 */ 399 private static class StringDataValidator extends HDFDataValidator { 400 private final Datatype datasetDatatype; 401 private final boolean isH5String; 402 403 StringDataValidator(final Datatype dtype) throws Exception { 404 super(dtype); 405 406 log = org.slf4j.LoggerFactory.getLogger(StringDataValidator.class); 407 408 if (!dtype.isString()) { 409 log.debug("datatype is not a String type"); 410 throw new Exception("StringDataValidator: datatype is not a String type"); 411 } 412 413 log.trace("StringDataValidator: base Datatype is {}", dtype.getDescription()); 414 415 this.datasetDatatype = dtype; 416 417 this.isH5String = (dtype instanceof H5Datatype); 418 } 419 420 @Override 421 public boolean validate(int colIndex, int rowIndex, Object newValue) { 422 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 423 424 try { 425 super.checkValidValue(newValue); 426 427 /* 428 * If this is a fixed-length string type, check to make sure that the data 429 * length does not exceed the datatype size. 430 */ 431 if (!datasetDatatype.isVarStr()) { 432 long lenDiff = ((String) newValue).length() - datasetDatatype.getDatatypeSize(); 433 434 if (lenDiff > 0) 435 throw new Exception("string size larger than datatype size by " + lenDiff 436 + ((lenDiff > 1) ? " bytes." : " byte.")); 437 438 /* 439 * TODO: Add Warning about overwriting NULL-terminator character. 440 */ 441 if (lenDiff == 0 && isH5String) { 442 H5Datatype h5Type = (H5Datatype) datasetDatatype; 443 int strPad = h5Type.getNativeStrPad(); 444 445 if (strPad == HDF5Constants.H5T_STR_NULLTERM) { 446 447 } 448 else if (strPad == HDF5Constants.H5T_STR_NULLPAD) { 449 450 } 451 else if (strPad == HDF5Constants.H5T_STR_SPACEPAD) { 452 453 } 454 } 455 } 456 } 457 catch (Exception ex) { 458 log.debug("validate({}, {}, {}): failed to validate: ", rowIndex, colIndex, newValue, ex); 459 super.throwValidationFailedException(rowIndex, colIndex, newValue, ex.getMessage()); 460 } 461 finally { 462 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 463 } 464 465 return true; 466 } 467 } 468 469 private static class CharDataValidator extends HDFDataValidator { 470 private final Datatype datasetDatatype; 471 472 CharDataValidator(final Datatype dtype) throws Exception { 473 super(dtype); 474 475 log = org.slf4j.LoggerFactory.getLogger(CharDataValidator.class); 476 477 if (!dtype.isChar()) { 478 log.debug("datatype is not a Character type"); 479 throw new Exception("CharDataValidator: datatype is not a Character type"); 480 } 481 482 this.datasetDatatype = dtype; 483 } 484 485 @Override 486 public boolean validate(int colIndex, int rowIndex, Object newValue) { 487 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 488 489 try { 490 if (datasetDatatype.isUnsigned()) { 491 /* 492 * First try to parse as a larger type in order to catch a NumberFormatException 493 */ 494 Short shortValue = Short.parseShort((String) newValue); 495 if (shortValue < 0) 496 throw new NumberFormatException("Invalid negative value for unsigned datatype"); 497 498 if (shortValue > (Byte.MAX_VALUE * 2) + 1) 499 throw new NumberFormatException("Value out of range. Value:\"" + newValue + "\""); 500 } 501 else { 502 Byte.parseByte((String) newValue); 503 } 504 } 505 catch (Exception ex) { 506 super.throwValidationFailedException(rowIndex, colIndex, newValue, ex.toString()); 507 } 508 finally { 509 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 510 } 511 512 return true; 513 } 514 515 } 516 517 /* 518 * NatTable DataValidator to validate entered input for a dataset with 519 * a numerical Datatype. 520 */ 521 private static class NumericalDataValidator extends HDFDataValidator { 522 private final Datatype datasetDatatype; 523 524 NumericalDataValidator(Datatype dtype) throws Exception { 525 super(dtype); 526 527 log = org.slf4j.LoggerFactory.getLogger(NumericalDataValidator.class); 528 529 if (!dtype.isInteger() && !dtype.isFloat()) { 530 log.debug("datatype is not an integer or floating-point type"); 531 throw new Exception("NumericalDataValidator: datatype is not an integer or floating-point type"); 532 } 533 534 log.trace("NumericalDataValidator: base Datatype is {}", dtype.getDescription()); 535 536 this.datasetDatatype = dtype; 537 } 538 539 @Override 540 public boolean validate(int colIndex, int rowIndex, Object newValue) { 541 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 542 543 try { 544 super.checkValidValue(newValue); 545 546 switch ((int) datasetDatatype.getDatatypeSize()) { 547 case 1: 548 if (datasetDatatype.isUnsigned()) { 549 /* 550 * First try to parse as a larger type in order to catch a NumberFormatException 551 */ 552 Short shortValue = Short.parseShort((String) newValue); 553 if (shortValue < 0) 554 throw new NumberFormatException("Invalid negative value for unsigned datatype"); 555 556 if (shortValue > (Byte.MAX_VALUE * 2) + 1) 557 throw new NumberFormatException("Value out of range. Value:\"" + newValue + "\""); 558 } 559 else { 560 Byte.parseByte((String) newValue); 561 } 562 break; 563 564 case 2: 565 if (datasetDatatype.isUnsigned()) { 566 /* 567 * First try to parse as a larger type in order to catch a NumberFormatException 568 */ 569 Integer intValue = Integer.parseInt((String) newValue); 570 if (intValue < 0) 571 throw new NumberFormatException("Invalid negative value for unsigned datatype"); 572 573 if (intValue > (Short.MAX_VALUE * 2) + 1) 574 throw new NumberFormatException("Value out of range. Value:\"" + newValue + "\""); 575 } 576 else { 577 Short.parseShort((String) newValue); 578 } 579 break; 580 581 case 4: 582 if (datasetDatatype.isInteger()) { 583 if (datasetDatatype.isUnsigned()) { 584 /* 585 * First try to parse as a larger type in order to catch a NumberFormatException 586 */ 587 Long longValue = Long.parseLong((String) newValue); 588 if (longValue < 0) 589 throw new NumberFormatException("Invalid negative value for unsigned datatype"); 590 591 if (longValue > ((long) Integer.MAX_VALUE * 2) + 1) 592 throw new NumberFormatException("Value out of range. Value:\"" + newValue + "\""); 593 } 594 else { 595 Integer.parseInt((String) newValue); 596 } 597 } 598 else { 599 /* Floating-point type */ 600 Float.parseFloat((String) newValue); 601 } 602 break; 603 604 case 8: 605 if (datasetDatatype.isInteger()) { 606 if (datasetDatatype.isUnsigned()) { 607 /* 608 * First try to parse as a larger type in order to catch a NumberFormatException 609 */ 610 BigInteger bigValue = new BigInteger((String) newValue); 611 if (bigValue.compareTo(BigInteger.ZERO) < 0) 612 throw new NumberFormatException("Invalid negative value for unsigned datatype"); 613 614 BigInteger maxRange = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(1)); 615 if (bigValue.compareTo(maxRange) > 0) 616 throw new NumberFormatException("Value out of range. Value:\"" + newValue + "\""); 617 } 618 else { 619 Long.parseLong((String) newValue); 620 } 621 } 622 else { 623 /* Floating-point type */ 624 Double.parseDouble((String) newValue); 625 } 626 break; 627 628 default: 629 throw new ValidationFailedException("No validation logic for numerical data of size " + datasetDatatype.getDatatypeSize()); 630 } 631 } 632 catch (Exception ex) { 633 super.throwValidationFailedException(rowIndex, colIndex, newValue, ex.toString()); 634 } 635 finally { 636 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 637 } 638 639 return true; 640 } 641 } 642 643 private static class EnumDataValidator extends HDFDataValidator { 644 private final HDFDataValidator baseValidator; 645 646 EnumDataValidator(final Datatype dtype) throws Exception { 647 super(dtype); 648 649 log = org.slf4j.LoggerFactory.getLogger(EnumDataValidator.class); 650 651 if (!dtype.isEnum()) { 652 log.debug("datatype is not an enum type: exit"); 653 throw new Exception("EnumDataValidator: datatype is not an enum type"); 654 } 655 656 Datatype baseType = dtype.getDatatypeBase(); 657 if (baseType == null) { 658 log.debug("base datatype is null: exit"); 659 throw new Exception("EnumDataValidator: base datatype is null"); 660 } 661 if (!baseType.isInteger()) { 662 log.debug("base datatype is not an integer type: exit"); 663 throw new Exception("EnumDataValidator: datatype is not an integer type"); 664 } 665 666 log.trace("base Datatype is {}", dtype.getDescription()); 667 668 try { 669 baseValidator = getDataValidator(baseType); 670 } 671 catch (Exception ex) { 672 log.debug("couldn't get DataValidator for base datatype: exit: ", ex); 673 throw new Exception("couldn't get DataValidator for base datatype: " + ex.getMessage()); 674 } 675 } 676 677 @Override 678 public boolean validate(int colIndex, int rowIndex, Object newValue) { 679 log.trace("validate({}, {}, {}): start", rowIndex, colIndex, newValue); 680 681 try { 682 super.checkValidValue(newValue); 683 684 baseValidator.validate(colIndex, rowIndex, newValue); 685 } 686 catch (Exception ex) { 687 super.throwValidationFailedException(rowIndex, colIndex, newValue, ex.toString()); 688 } 689 finally { 690 log.trace("validate({}, {}, {}): finish", rowIndex, colIndex, newValue); 691 } 692 693 return true; 694 } 695 } 696 697 private static class BitfieldDataValidator extends HDFDataValidator { 698 BitfieldDataValidator(final Datatype dtype) { 699 super(dtype); 700 701 log = org.slf4j.LoggerFactory.getLogger(BitfieldDataValidator.class); 702 } 703 } 704 705 private static class RefDataValidator extends HDFDataValidator { 706 RefDataValidator(final Datatype dtype) { 707 super(dtype); 708 709 log = org.slf4j.LoggerFactory.getLogger(RefDataValidator.class); 710 } 711 } 712 713}