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