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