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