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