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