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