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