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.lang.reflect.Array; 017import java.math.BigInteger; 018import java.text.NumberFormat; 019import java.util.HashMap; 020import java.util.List; 021 022import hdf.object.CompoundDataFormat; 023import hdf.object.DataFormat; 024import hdf.object.Datatype; 025import hdf.object.h5.H5Datatype; 026import hdf.view.Tools; 027 028import hdf.hdf5lib.exceptions.HDF5Exception; 029 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; 034import org.eclipse.nebula.widgets.nattable.data.convert.DisplayConverter; 035import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; 036 037/** 038 * A Factory class to return a concrete class implementing the IDisplayConverter 039 * interface in order to convert data values into human-readable forms in a NatTable. 040 * The returned class is also responsible for converting the human-readable form back 041 * into real data when writing the data object back to the file. 042 * 043 * @author Jordan T. Henderson 044 * @version 1.0 2/9/2019 045 * 046 */ 047public class DataDisplayConverterFactory { 048 private static final Logger log = LoggerFactory.getLogger(DataDisplayConverterFactory.class); 049 050 /** 051 * To keep things clean from an API perspective, keep a static reference to the last 052 * CompoundDataFormat that was passed in. This keeps us from needing to pass the 053 * CompoundDataFormat object as a parameter to every DataDisplayConverter class, 054 * since it's really only needed by the CompoundDataDisplayConverter. 055 */ 056 private static DataFormat dataFormatReference = null; 057 058 /** 059 * Get the Data Display Converter for the supplied data object 060 * 061 * @param dataObject 062 * the data object 063 * 064 * @return the converter instance 065 * 066 * @throws Exception if a failure occurred 067 */ 068 public static HDFDisplayConverter getDataDisplayConverter(final DataFormat dataObject) throws Exception 069 { 070 if (dataObject == null) { 071 log.debug("getDataDisplayConverter(DataFormat): data object is null"); 072 return null; 073 } 074 075 dataFormatReference = dataObject; 076 077 HDFDisplayConverter converter = getDataDisplayConverter(dataObject.getDatatype()); 078 079 return converter; 080 } 081 082 private static final HDFDisplayConverter getDataDisplayConverter(final Datatype dtype) throws Exception 083 { 084 HDFDisplayConverter converter = null; 085 086 try { 087 if (dtype.isCompound()) 088 converter = new CompoundDataDisplayConverter(dtype); 089 else if (dtype.isArray()) 090 converter = new ArrayDataDisplayConverter(dtype); 091 else if (dtype.isVLEN() && !dtype.isVarStr()) 092 converter = new VlenDataDisplayConverter(dtype); 093 else if (dtype.isString() || dtype.isVarStr()) 094 converter = new StringDataDisplayConverter(dtype); 095 else if (dtype.isChar()) 096 converter = new CharDataDisplayConverter(dtype); 097 else if (dtype.isInteger() || dtype.isFloat()) 098 converter = new NumericalDataDisplayConverter(dtype); 099 else if (dtype.isEnum()) 100 converter = new EnumDataDisplayConverter(dtype); 101 else if (dtype.isOpaque() || dtype.isBitField()) 102 converter = new BitfieldDataDisplayConverter(dtype); 103 else if (dtype.isRef()) 104 converter = new RefDataDisplayConverter(dtype); 105 } 106 catch (Exception ex) { 107 log.debug( 108 "getDataDisplayConverter(Datatype): error occurred in retrieving a DataDisplayConverter: ", 109 ex); 110 converter = null; 111 } 112 113 /* 114 * Try to use a default converter. 115 */ 116 if (converter == null) { 117 log.debug("getDataDisplayConverter(Datatype): using a default data display converter"); 118 119 converter = new HDFDisplayConverter(dtype); 120 } 121 122 return converter; 123 } 124 125 /** the HDF extension for data converters */ 126 public static class HDFDisplayConverter extends DisplayConverter { 127 private static final Logger log = LoggerFactory.getLogger(HDFDisplayConverter.class); 128 129 /** the number format type */ 130 protected NumberFormat numberFormat = null; 131 /** if the data shows in hex format */ 132 protected boolean showAsHex = false; 133 /** if data shows in binary format */ 134 protected boolean showAsBin = false; 135 /** if the enum mapped value is shown */ 136 protected boolean isEnumConverted = false; 137 138 /** 139 * This field is only used for CompoundDataDisplayConverters, but when the 140 * top-level DisplayConverter is a "container" type, such as an 141 * ArrayDataDisplayConverter, we have to set this field and pass it through in 142 * case there is a CompoundDataDisplayConverter at the bottom of the chain. 143 */ 144 /** the "container" type row index */ 145 protected int cellRowIdx; 146 /** the "container" type column index */ 147 protected int cellColIdx; 148 149 /** 150 * create a HDF data converter 151 * 152 * @param dtype 153 * the datatype for conversion 154 */ 155 HDFDisplayConverter(final Datatype dtype) 156 { 157 cellRowIdx = -1; 158 cellColIdx = -1; 159 } 160 161 @Override 162 public Object canonicalToDisplayValue(Object value) 163 { 164 log.trace("canonicalToDisplayValue({}): start", value); 165 166 if (value instanceof String) 167 return value; 168 169 if (value == null) { 170 log.debug("canonicalToDisplayValue({}): value is null", value); 171 return DataFactoryUtils.nullStr; 172 } 173 174 return value; 175 } 176 177 @Override 178 public Object displayToCanonicalValue(Object value) 179 { 180 log.trace("displayToCanonicalValue({}): start", value); 181 return value; 182 } 183 184 /** 185 * set the number format type 186 * 187 * @param format 188 * the data format 189 */ 190 public void setNumberFormat(NumberFormat format) { numberFormat = format; } 191 192 /** 193 * set if the data shows in hex format 194 * 195 * @param asHex 196 * if the data shows as hex format 197 */ 198 public void setShowAsHex(boolean asHex) { showAsHex = asHex; } 199 200 /** 201 * set if data shows in binary format 202 * 203 * @param asBin 204 * if the data shows as binary format 205 */ 206 public void setShowAsBin(boolean asBin) { showAsBin = asBin; } 207 208 /** 209 * set if the enum mapped value is shown 210 * 211 * @param convert 212 * if the enum data should be converted 213 */ 214 public void setConvertEnum(boolean convert) { isEnumConverted = convert; } 215 } 216 217 private static class CompoundDataDisplayConverter extends HDFDisplayConverter { 218 private static final Logger log = LoggerFactory.getLogger(CompoundDataDisplayConverter.class); 219 220 private final HashMap<Integer, Integer> baseConverterIndexMap; 221 private final HashMap<Integer, Integer> relCmpdStartIndexMap; 222 private final HDFDisplayConverter[] memberTypeConverters; 223 private final StringBuilder buffer; 224 private final int nTotFields; 225 226 CompoundDataDisplayConverter(final Datatype dtype) throws Exception 227 { 228 super(dtype); 229 230 if (!dtype.isCompound()) { 231 log.debug("datatype is not a compound type"); 232 throw new Exception("CompoundDataDisplayConverter: datatype is not a compound type"); 233 } 234 235 CompoundDataFormat compoundFormat = (CompoundDataFormat)dataFormatReference; 236 237 List<Datatype> localSelectedTypes = 238 DataFactoryUtils.filterNonSelectedMembers(compoundFormat, dtype); 239 240 log.trace("setting up {} base HDFDisplayConverters", localSelectedTypes.size()); 241 242 memberTypeConverters = new HDFDisplayConverter[localSelectedTypes.size()]; 243 for (int i = 0; i < memberTypeConverters.length; i++) { 244 log.trace("retrieving DataDisplayConverter for member {}", i); 245 246 try { 247 memberTypeConverters[i] = getDataDisplayConverter(localSelectedTypes.get(i)); 248 249 /* 250 * Make base datatype converters inherit the data conversion settings. 251 */ 252 memberTypeConverters[i].setShowAsHex(this.showAsHex); 253 memberTypeConverters[i].setShowAsBin(this.showAsBin); 254 memberTypeConverters[i].setNumberFormat(this.numberFormat); 255 memberTypeConverters[i].setConvertEnum(this.isEnumConverted); 256 } 257 catch (Exception ex) { 258 log.debug("failed to retrieve DataDisplayConverter for member {}: ", i, ex); 259 memberTypeConverters[i] = null; 260 } 261 } 262 263 /* 264 * Build necessary index maps. 265 */ 266 HashMap<Integer, Integer>[] maps = 267 DataFactoryUtils.buildIndexMaps(compoundFormat, localSelectedTypes); 268 baseConverterIndexMap = maps[DataFactoryUtils.COL_TO_BASE_CLASS_MAP_INDEX]; 269 relCmpdStartIndexMap = maps[DataFactoryUtils.CMPD_START_IDX_MAP_INDEX]; 270 271 log.trace("index maps built: baseConverterIndexMap = {}, relColIdxMap = {}", 272 baseConverterIndexMap, relCmpdStartIndexMap); 273 274 if (baseConverterIndexMap.size() == 0) { 275 log.debug("base DataDisplayConverter index mapping is invalid - size 0"); 276 throw new Exception( 277 "CompoundDataDisplayConverter: invalid DataDisplayConverter mapping of size 0 built"); 278 } 279 280 if (relCmpdStartIndexMap.size() == 0) { 281 log.debug("compound field start index mapping is invalid - size 0"); 282 throw new Exception( 283 "CompoundDataDisplayConverter: invalid compound field start index mapping of size 0 built"); 284 } 285 286 nTotFields = baseConverterIndexMap.size(); 287 288 buffer = new StringBuilder(); 289 } 290 291 @Override 292 public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object value) 293 { 294 cellRowIdx = cell.getRowIndex(); 295 cellColIdx = cell.getColumnIndex() % nTotFields; 296 return canonicalToDisplayValue(value); 297 } 298 299 @Override 300 public Object canonicalToDisplayValue(Object value) 301 { 302 log.trace("canonicalToDisplayValue({}): start", value); 303 304 if (value instanceof String) 305 return value; 306 307 if (value == null) { 308 log.debug("canonicalToDisplayValue({}): value is null", value); 309 return DataFactoryUtils.nullStr; 310 } 311 312 buffer.setLength(0); // clear the old string 313 314 try { 315 if (cellColIdx >= nTotFields) 316 cellColIdx %= nTotFields; 317 318 if (value instanceof List) { 319 /* 320 * For Arrays of Compounds, we convert an entire list of data. 321 */ 322 List<?> cmpdList = (List<?>)value; 323 324 buffer.append("{"); 325 for (int i = 0; i < memberTypeConverters.length; i++) { 326 if (i > 0) 327 buffer.append(", "); 328 329 Object curObject = cmpdList.get(i); 330 if (curObject instanceof List) 331 buffer.append(memberTypeConverters[i].canonicalToDisplayValue(curObject)); 332 else { 333 Object dataArrayValue = Array.get(curObject, cellRowIdx); 334 buffer.append(memberTypeConverters[i].canonicalToDisplayValue(dataArrayValue)); 335 } 336 } 337 buffer.append("}"); 338 } 339 else { 340 HDFDisplayConverter converter = 341 memberTypeConverters[baseConverterIndexMap.get(cellColIdx)]; 342 converter.cellRowIdx = cellRowIdx; 343 converter.cellColIdx = cellColIdx - relCmpdStartIndexMap.get(cellColIdx); 344 345 buffer.append(converter.canonicalToDisplayValue(value)); 346 } 347 } 348 catch (Exception ex) { 349 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 350 buffer.setLength(0); 351 buffer.append(DataFactoryUtils.errStr); 352 } 353 354 return buffer; 355 } 356 357 @Override 358 public void setNumberFormat(NumberFormat format) 359 { 360 super.setNumberFormat(format); 361 362 for (int i = 0; i < memberTypeConverters.length; i++) 363 memberTypeConverters[i].setNumberFormat(format); 364 } 365 366 @Override 367 public void setShowAsHex(boolean asHex) 368 { 369 super.setShowAsHex(asHex); 370 371 for (int i = 0; i < memberTypeConverters.length; i++) 372 memberTypeConverters[i].setShowAsHex(asHex); 373 } 374 375 @Override 376 public void setShowAsBin(boolean asBin) 377 { 378 super.setShowAsBin(asBin); 379 380 for (int i = 0; i < memberTypeConverters.length; i++) 381 memberTypeConverters[i].setShowAsBin(asBin); 382 } 383 384 @Override 385 public void setConvertEnum(boolean convert) 386 { 387 super.setConvertEnum(convert); 388 389 for (int i = 0; i < memberTypeConverters.length; i++) 390 memberTypeConverters[i].setConvertEnum(convert); 391 } 392 } 393 394 private static class ArrayDataDisplayConverter extends HDFDisplayConverter { 395 private static final Logger log = LoggerFactory.getLogger(ArrayDataDisplayConverter.class); 396 397 private final HDFDisplayConverter baseTypeConverter; 398 private final StringBuilder buffer; 399 400 ArrayDataDisplayConverter(final Datatype dtype) throws Exception 401 { 402 super(dtype); 403 404 if (!dtype.isArray()) { 405 log.debug("exit: datatype is not an array type"); 406 throw new Exception("ArrayDataDisplayConverter: datatype is not an array type"); 407 } 408 409 Datatype baseType = dtype.getDatatypeBase(); 410 411 if (baseType == null) { 412 log.debug("exit: base datatype is null"); 413 throw new Exception("ArrayDataDisplayConverter: base datatype is null"); 414 } 415 416 try { 417 baseTypeConverter = getDataDisplayConverter(baseType); 418 419 /* 420 * Make base datatype converter inherit the data conversion settings. 421 */ 422 baseTypeConverter.setShowAsHex(this.showAsHex); 423 baseTypeConverter.setShowAsBin(this.showAsBin); 424 baseTypeConverter.setNumberFormat(this.numberFormat); 425 baseTypeConverter.setConvertEnum(this.isEnumConverted); 426 } 427 catch (Exception ex) { 428 log.debug("exit: couldn't get DataDisplayConverter for base datatype: ", ex); 429 throw new Exception( 430 "ArrayDataDisplayConverter: couldn't get DataDisplayConverter for base datatype: " + 431 ex.getMessage()); 432 } 433 434 buffer = new StringBuilder(); 435 } 436 437 @Override 438 public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object value) 439 { 440 cellRowIdx = cell.getRowIndex(); 441 cellColIdx = cell.getColumnIndex(); 442 return canonicalToDisplayValue(value); 443 } 444 445 @Override 446 public Object canonicalToDisplayValue(Object value) 447 { 448 log.trace("canonicalToDisplayValue({}): start", value); 449 450 if (value instanceof String) 451 return value; 452 453 if (value == null) { 454 log.debug("canonicalToDisplayValue({}): value is null", value); 455 return DataFactoryUtils.nullStr; 456 } 457 458 buffer.setLength(0); // clear the old string 459 460 /* 461 * Pass the cell's row and column index down in case there is a 462 * CompoundDataDisplayConverter at the bottom of the chain. 463 */ 464 baseTypeConverter.cellRowIdx = cellRowIdx; 465 baseTypeConverter.cellColIdx = cellColIdx; 466 467 try { 468 Object obj; 469 Object convertedValue; 470 int arrLen = Array.getLength(value); 471 472 log.trace("canonicalToDisplayValue({}): array length={}", value, arrLen); 473 474 if (!(baseTypeConverter instanceof CompoundDataDisplayConverter)) 475 buffer.append("["); 476 477 for (int i = 0; i < arrLen; i++) { 478 if (i > 0) 479 buffer.append(", "); 480 481 obj = Array.get(value, i); 482 483 convertedValue = baseTypeConverter.canonicalToDisplayValue(obj); 484 485 buffer.append(convertedValue); 486 } 487 488 if (!(baseTypeConverter instanceof CompoundDataDisplayConverter)) 489 buffer.append("]"); 490 } 491 catch (Exception ex) { 492 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 493 buffer.setLength(0); 494 buffer.append(DataFactoryUtils.errStr); 495 } 496 497 return buffer; 498 } 499 500 @Override 501 public void setNumberFormat(NumberFormat format) 502 { 503 super.setNumberFormat(format); 504 505 baseTypeConverter.setNumberFormat(format); 506 } 507 508 @Override 509 public void setShowAsHex(boolean asHex) 510 { 511 super.setShowAsHex(asHex); 512 513 baseTypeConverter.setShowAsHex(asHex); 514 } 515 516 @Override 517 public void setShowAsBin(boolean asBin) 518 { 519 super.setShowAsBin(asBin); 520 521 baseTypeConverter.setShowAsBin(asBin); 522 } 523 524 @Override 525 public void setConvertEnum(boolean convert) 526 { 527 super.setConvertEnum(convert); 528 529 baseTypeConverter.setConvertEnum(convert); 530 } 531 } 532 533 private static class VlenDataDisplayConverter extends HDFDisplayConverter { 534 private static final Logger log = LoggerFactory.getLogger(VlenDataDisplayConverter.class); 535 536 private final HDFDisplayConverter baseTypeConverter; 537 private final StringBuilder buffer; 538 539 VlenDataDisplayConverter(final Datatype dtype) throws Exception 540 { 541 super(dtype); 542 543 if (!dtype.isVLEN() || dtype.isVarStr()) { 544 log.debug( 545 "exit: datatype is not a variable-length type or is a variable-length string type (use StringDataDisplayConverter)"); 546 throw new Exception( 547 "VlenDataDisplayConverter: datatype is not a variable-length type or is a variable-length string type (use StringDataDisplayConverter)"); 548 } 549 550 Datatype baseType = dtype.getDatatypeBase(); 551 552 if (baseType == null) { 553 log.debug("base datatype is null"); 554 throw new Exception("VlenDataDisplayConverter: base datatype is null"); 555 } 556 557 try { 558 baseTypeConverter = getDataDisplayConverter(baseType); 559 560 /* 561 * Make base datatype converter inherit the data conversion settings. 562 */ 563 baseTypeConverter.setShowAsHex(this.showAsHex); 564 baseTypeConverter.setShowAsBin(this.showAsBin); 565 baseTypeConverter.setNumberFormat(this.numberFormat); 566 baseTypeConverter.setConvertEnum(this.isEnumConverted); 567 } 568 catch (Exception ex) { 569 log.debug("couldn't get DataDisplayConverter for base datatype: ", ex); 570 throw new Exception( 571 "VlenDataDisplayConverter: couldn't get DataDisplayConverter for base datatype: " + 572 ex.getMessage()); 573 } 574 575 buffer = new StringBuilder(); 576 } 577 578 @Override 579 public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object value) 580 { 581 cellRowIdx = cell.getRowIndex(); 582 cellColIdx = cell.getColumnIndex(); 583 return canonicalToDisplayValue(value); 584 } 585 586 @Override 587 public Object canonicalToDisplayValue(Object value) 588 { 589 log.trace("canonicalToDisplayValue({}): start", value); 590 591 if (value instanceof String) 592 return value; 593 594 if (value == null) { 595 log.debug("canonicalToDisplayValue({}): value is null", value); 596 return DataFactoryUtils.nullStr; 597 } 598 599 buffer.setLength(0); // clear the old string 600 601 /* 602 * Pass the cell's row and column index down in case there is a 603 * CompoundDataDisplayConverter at the bottom of the chain. 604 */ 605 baseTypeConverter.cellRowIdx = cellRowIdx; 606 baseTypeConverter.cellColIdx = cellColIdx; 607 608 try { 609 Object obj; 610 Object convertedValue; 611 int arrLen = Array.getLength(value); 612 613 log.trace("canonicalToDisplayValue({}): array length={}", value, arrLen); 614 615 if (!(baseTypeConverter instanceof RefDataDisplayConverter)) 616 buffer.append("["); 617 618 for (int i = 0; i < arrLen; i++) { 619 if (i > 0) 620 buffer.append(", "); 621 622 obj = Array.get(value, i); 623 624 convertedValue = baseTypeConverter.canonicalToDisplayValue(obj); 625 626 buffer.append(convertedValue); 627 } 628 629 if (!(baseTypeConverter instanceof RefDataDisplayConverter)) 630 buffer.append("]"); 631 } 632 catch (Exception ex) { 633 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 634 buffer.setLength(0); 635 buffer.append(DataFactoryUtils.errStr); 636 } 637 638 return buffer; 639 } 640 641 @Override 642 public void setNumberFormat(NumberFormat format) 643 { 644 super.setNumberFormat(format); 645 646 baseTypeConverter.setNumberFormat(format); 647 } 648 649 @Override 650 public void setShowAsHex(boolean asHex) 651 { 652 super.setShowAsHex(asHex); 653 654 baseTypeConverter.setShowAsHex(asHex); 655 } 656 657 @Override 658 public void setShowAsBin(boolean asBin) 659 { 660 super.setShowAsBin(asBin); 661 662 baseTypeConverter.setShowAsBin(asBin); 663 } 664 665 @Override 666 public void setConvertEnum(boolean convert) 667 { 668 super.setConvertEnum(convert); 669 670 baseTypeConverter.setConvertEnum(convert); 671 } 672 } 673 674 private static class StringDataDisplayConverter extends HDFDisplayConverter { 675 private static final Logger log = LoggerFactory.getLogger(StringDataDisplayConverter.class); 676 677 StringDataDisplayConverter(final Datatype dtype) throws Exception 678 { 679 super(dtype); 680 681 if (!dtype.isString() && !dtype.isVarStr()) { 682 log.debug("datatype is not a string type"); 683 throw new Exception("StringDataDisplayConverter: datatype is not a string type"); 684 } 685 } 686 } 687 688 private static class CharDataDisplayConverter extends HDFDisplayConverter { 689 private static final Logger log = LoggerFactory.getLogger(CharDataDisplayConverter.class); 690 691 CharDataDisplayConverter(final Datatype dtype) throws Exception 692 { 693 super(dtype); 694 695 if (!dtype.isChar()) { 696 log.debug("datatype is not a character type"); 697 throw new Exception("CharDataDisplayConverter: datatype is not a character type"); 698 } 699 } 700 701 @Override 702 public Object displayToCanonicalValue(Object value) 703 { 704 char charValue = ((String)value).charAt(0); 705 return (int)charValue; 706 } 707 } 708 709 private static class NumericalDataDisplayConverter extends HDFDisplayConverter { 710 private static final Logger log = LoggerFactory.getLogger(NumericalDataDisplayConverter.class); 711 712 private final StringBuilder buffer; 713 private final long typeSize; 714 private final boolean isUINT64; 715 private final boolean isFLT16; 716 717 NumericalDataDisplayConverter(final Datatype dtype) throws Exception 718 { 719 super(dtype); 720 721 if (!dtype.isInteger() && !dtype.isFloat()) { 722 log.debug("datatype is not an integer or floating-point type"); 723 throw new Exception( 724 "NumericalDataDisplayConverter: datatype is not an integer or floating-point type"); 725 } 726 727 buffer = new StringBuilder(); 728 729 typeSize = dtype.getDatatypeSize(); 730 isUINT64 = dtype.isUnsigned() && (typeSize == 8); 731 isFLT16 = dtype.isFloat() && (typeSize == 2); 732 } 733 734 @Override 735 public Object canonicalToDisplayValue(Object value) 736 { 737 log.trace("canonicalToDisplayValue({}): start", value); 738 739 if (value instanceof String) 740 return value; 741 742 if (value == null) { 743 log.debug("canonicalToDisplayValue({}): value is null", value); 744 return DataFactoryUtils.nullStr; 745 } 746 747 buffer.setLength(0); // clear the old string 748 749 try { 750 if (showAsHex) { 751 if (isUINT64) 752 buffer.append(Tools.toHexString((BigInteger)value, 8)); 753 else 754 buffer.append(Tools.toHexString(Long.valueOf(value.toString()), (int)typeSize)); 755 } 756 else if (showAsBin) { 757 if (isUINT64) 758 buffer.append(Tools.toBinaryString((BigInteger)value, 8)); 759 else 760 buffer.append(Tools.toBinaryString(Long.valueOf(value.toString()), (int)typeSize)); 761 } 762 else if (numberFormat != null) { 763 buffer.append(numberFormat.format(value)); 764 } 765 else { 766 buffer.append(value.toString()); 767 } 768 } 769 catch (Exception ex) { 770 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 771 buffer.setLength(0); 772 buffer.append(DataFactoryUtils.errStr); 773 } 774 775 return buffer; 776 } 777 } 778 779 private static class EnumDataDisplayConverter extends HDFDisplayConverter { 780 private static final Logger log = LoggerFactory.getLogger(EnumDataDisplayConverter.class); 781 782 private final StringBuilder buffer; 783 private final H5Datatype enumType; 784 785 EnumDataDisplayConverter(final Datatype dtype) throws Exception 786 { 787 super(dtype); 788 789 if (!dtype.isEnum()) { 790 log.debug("datatype is not an enum type"); 791 throw new Exception("EnumDataDisplayConverter: datatype is not an enum type"); 792 } 793 794 buffer = new StringBuilder(); 795 796 enumType = (H5Datatype)dtype; 797 } 798 799 @Override 800 public Object canonicalToDisplayValue(Object value) 801 { 802 log.trace("canonicalToDisplayValue({}): start", value); 803 804 if (value instanceof String) 805 return value; 806 807 if (value == null) { 808 log.debug("canonicalToDisplayValue({}): value is null", value); 809 return DataFactoryUtils.nullStr; 810 } 811 812 buffer.setLength(0); // clear the old string 813 814 try { 815 if (isEnumConverted) { 816 String[] retValues = null; 817 818 try { 819 retValues = enumType.convertEnumValueToName(value); 820 } 821 catch (HDF5Exception ex) { 822 log.trace("canonicalToDisplayValue({}): Could not convert enum values to names: ", 823 value, ex); 824 retValues = null; 825 } 826 827 if (retValues != null) 828 buffer.append(retValues[0]); 829 else 830 buffer.append(DataFactoryUtils.nullStr); 831 } 832 else 833 buffer.append(value); 834 } 835 catch (Exception ex) { 836 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 837 buffer.setLength(0); 838 buffer.append(DataFactoryUtils.errStr); 839 } 840 841 return buffer; 842 } 843 } 844 845 private static class BitfieldDataDisplayConverter extends HDFDisplayConverter { 846 private static final Logger log = LoggerFactory.getLogger(BitfieldDataDisplayConverter.class); 847 848 private final StringBuilder buffer; 849 private final boolean isOpaque; 850 851 BitfieldDataDisplayConverter(final Datatype dtype) throws Exception 852 { 853 super(dtype); 854 855 if (!dtype.isBitField() && !dtype.isOpaque()) { 856 log.debug("datatype is not a bitfield or opaque type"); 857 throw new Exception( 858 "BitfieldDataDisplayConverter: datatype is not a bitfield or opaque type"); 859 } 860 861 buffer = new StringBuilder(); 862 863 isOpaque = dtype.isOpaque(); 864 } 865 866 @Override 867 public Object canonicalToDisplayValue(Object value) 868 { 869 log.trace("canonicalToDisplayValue({}): start", value); 870 871 if (value instanceof String) 872 return value; 873 874 if (value == null) { 875 log.debug("canonicalToDisplayValue({}): value is null", value); 876 return DataFactoryUtils.nullStr; 877 } 878 879 buffer.setLength(0); // clear the old string 880 881 try { 882 for (int i = 0; i < ((byte[])value).length; i++) { 883 if (i > 0) 884 buffer.append(isOpaque ? " " : ":"); 885 886 buffer.append(Tools.toHexString((((byte[])value)[i]), 1)); 887 } 888 } 889 catch (Exception ex) { 890 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 891 buffer.setLength(0); 892 buffer.append(DataFactoryUtils.errStr); 893 } 894 895 return buffer; 896 } 897 } 898 899 private static class RefDataDisplayConverter extends HDFDisplayConverter { 900 private static final Logger log = LoggerFactory.getLogger(RefDataDisplayConverter.class); 901 902 private final StringBuilder buffer; 903 904 RefDataDisplayConverter(final Datatype dtype) throws Exception 905 { 906 super(dtype); 907 908 if (!dtype.isRef()) { 909 log.debug("datatype is not a reference type"); 910 throw new Exception("RefDataDisplayConverter: datatype is not a reference type"); 911 } 912 913 buffer = new StringBuilder(); 914 } 915 916 @Override 917 public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object value) 918 { 919 cellRowIdx = cell.getRowIndex(); 920 cellColIdx = cell.getColumnIndex(); 921 log.trace("canonicalToDisplayValue({}) cellRowIdx={} cellColIdx={}: start", value, cellRowIdx, 922 cellColIdx); 923 return canonicalToDisplayValue(value); 924 } 925 926 @Override 927 public Object canonicalToDisplayValue(Object value) 928 { 929 log.trace("canonicalToDisplayValue({}): start", value); 930 931 if (value instanceof String) 932 return value; 933 934 if (value == null) { 935 log.debug("canonicalToDisplayValue({}): value is null", value); 936 return DataFactoryUtils.nullStr; 937 } 938 939 buffer.setLength(0); // clear the old string 940 941 try { 942 Object obj; 943 Object convertedValue; 944 int arrLen = Array.getLength(value); 945 946 log.trace("canonicalToDisplayValue({}): array length={}", value, arrLen); 947 948 for (int i = 0; i < arrLen; i++) { 949 if (i > 0) 950 buffer.append(", "); 951 952 obj = Array.get(value, i); 953 954 buffer.append(obj); 955 } 956 } 957 catch (Exception ex) { 958 log.debug("canonicalToDisplayValue({}): failure: ", value, ex); 959 buffer.setLength(0); 960 buffer.append(DataFactoryUtils.errStr); 961 } 962 963 return buffer; 964 } 965 } 966}