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 COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.h4; 016 017import java.util.List; 018import java.util.Vector; 019 020import hdf.hdflib.HDFConstants; 021import hdf.hdflib.HDFException; 022import hdf.hdflib.HDFLibrary; 023import hdf.object.Attribute; 024import hdf.object.CompoundDS; 025import hdf.object.Dataset; 026import hdf.object.Datatype; 027import hdf.object.FileFormat; 028import hdf.object.Group; 029import hdf.object.MetaDataContainer; 030import hdf.object.h4.H4CompoundAttribute; 031 032/** 033 * H4Vdata describes a multi-dimension array of HDF4 vdata, inheriting CompoundDS. 034 * 035 * A vdata is like a table that consists of a collection of records whose values 036 * are stored in fixed-length fields. All records have the same structure and 037 * all values in each field have the same data type. Vdatas are uniquely 038 * identified by a name, a class, and a series of individual field names. 039 * 040 * <b>How to Select a Subset</b> 041 * 042 * Dataset defines APIs for reading, writing and subsetting a dataset. No function is 043 * defined to select a subset of a data array. The selection is done in an implicit way. 044 * Function calls to dimension information such as getSelectedDims() return an array 045 * of dimension values, which is a reference to the array in the dataset object. 046 * Changes of the array outside the dataset object directly change the values of 047 * the array in the dataset object. It is like pointers in C. 048 * 049 * The following is an example of how to make a subset. In the example, the dataset 050 * is a 4-dimension with size of [200][100][50][10], i.e. 051 * dims[0]=200; dims[1]=100; dims[2]=50; dims[3]=10; <br> 052 * We want to select every other data point in dims[1] and dims[2] 053 * <pre> 054 int rank = dataset.getRank(); // number of dimensions of the dataset 055 long[] dims = dataset.getDims(); // the dimension sizes of the dataset 056 long[] selected = dataset.getSelectedDims(); // the selected size of the dataet 057 long[] start = dataset.getStartDims(); // the offset of the selection 058 long[] stride = dataset.getStride(); // the stride of the dataset 059 int[] selectedIndex = dataset.getSelectedIndex(); // the selected dimensions for display 060 061 // select dim1 and dim2 as 2D data for display, and slice through dim0 062 selectedIndex[0] = 1; 063 selectedIndex[1] = 2; 064 selectedIndex[1] = 0; 065 066 // reset the selection arrays 067 for (int i=0; i<rank; i++) { 068 start[i] = 0; 069 selected[i] = 1; 070 stride[i] = 1; 071 } 072 073 // set stride to 2 on dim1 and dim2 so that every other data point is selected. 074 stride[1] = 2; 075 stride[2] = 2; 076 077 // set the selection size of dim1 and dim2 078 selected[1] = dims[1]/stride[1]; 079 selected[2] = dims[1]/stride[2]; 080 081 // when dataset.read() is called, the selection above will be used since 082 // the dimension arrays is passed by reference. Changes of these arrays 083 // outside the dataset object directly change the values of these array 084 // in the dataset object. 085 086 * </pre> 087 * 088 * @version 1.1 9/4/2007 089 * @author Peter X. Cao 090 */ 091public class H4Vdata extends CompoundDS implements MetaDataContainer { 092 private static final long serialVersionUID = -5978700886955419959L; 093 094 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(H4Vdata.class); 095 096 /** 097 * The list of attributes of this data object. Members of the list are 098 * instance of H4CompoundAttribute. 099 */ 100 @SuppressWarnings("rawtypes") 101 private List attributeList; 102 103 /** 104 * Number of records of this Vdata table. 105 */ 106 private int numberOfRecords; 107 108 /** 109 * The data types of the members of the compound dataset. 110 */ 111 private long[] memberTIDs; 112 113 /** the number of attributes */ 114 private int nAttributes = -1; 115 116 /** 117 * Creates an H4Vdata object with specific name and path. 118 * 119 * @param theFile the HDF file. 120 * @param name the name of this H4Vdata. 121 * @param path the full path of this H4Vdata. 122 */ 123 public H4Vdata(FileFormat theFile, String name, String path) { this(theFile, name, path, null); } 124 125 /** 126 * Creates an H4Vdata object with specific name, path and oid. 127 * 128 * @param theFile the HDF file. 129 * @param name the name of this H4Vdata. 130 * @param path the full path of this H4Vdata. 131 * @param oid the unique identifier of this data object. 132 */ 133 @SuppressWarnings("deprecation") 134 public H4Vdata(FileFormat theFile, String name, String path, long[] oid) 135 { 136 super(theFile, name, path, oid); 137 numberOfRecords = 0; 138 numberOfMembers = 0; 139 memberOrders = null; 140 } 141 142 /* 143 * (non-Javadoc) 144 * @see hdf.object.DataFormat#hasAttribute() 145 */ 146 @Override 147 public boolean hasAttribute() 148 { 149 if (nAttributes < 0) { 150 long id = open(); 151 152 if (id >= 0) { 153 try { 154 nAttributes = HDFLibrary.VSnattrs(id); 155 } 156 catch (Exception ex) { 157 log.debug("hasAttribute() failure: ", ex); 158 nAttributes = 0; 159 } 160 161 log.trace("hasAttribute(): nAttributes={}", nAttributes); 162 163 close(id); 164 } 165 } 166 167 return (nAttributes > 0); 168 } 169 170 // implementing Dataset 171 /** 172 * Returns the datatype of the data object. 173 * 174 * @return the datatype of the data object. 175 */ 176 @Override 177 public Datatype getDatatype() 178 { 179 if (!inited) 180 init(); 181 182 if (datatype == null) { 183 try { 184 datatype = new H4Datatype(-1); 185 } 186 catch (Exception ex) { 187 log.debug("getDatatype(): failed to create datatype: ", ex); 188 datatype = null; 189 } 190 } 191 192 return datatype; 193 } 194 195 /** 196 * Returns the fill values for the data object. 197 * 198 * @return the fill values for the data object. 199 */ 200 @Override 201 public Object getFillValue() 202 { 203 return null; 204 } 205 206 // Implementing Dataset 207 @Override 208 public byte[] readBytes() throws HDFException 209 { 210 byte[] theData = null; 211 212 if (!isInited()) 213 init(); 214 215 if (numberOfMembers <= 0) { 216 log.debug("readBytes(): VData contains no members"); 217 return null; // this Vdata does not have any filed 218 } 219 220 long id = open(); 221 if (id < 0) { 222 log.debug("readBytes(): Invalid VData ID"); 223 return null; 224 } 225 226 String allNames = memberNames[0]; 227 for (int i = 0; i < numberOfMembers; i++) 228 allNames += "," + memberNames[i]; 229 230 try { 231 // moves the access pointer to the start position 232 HDFLibrary.VSseek(id, (int)startDims[0]); 233 // Specify the fields to be accessed 234 HDFLibrary.VSsetfields(id, allNames); 235 int[] recordSize = {0}; 236 HDFLibrary.VSQueryvsize(id, recordSize); 237 int size = recordSize[0] * (int)selectedDims[0]; 238 theData = new byte[size]; 239 HDFLibrary.VSread(id, theData, (int)selectedDims[0], HDFConstants.FULL_INTERLACE); 240 } 241 catch (Exception ex) { 242 log.debug("readBytes(): failure: ", ex); 243 } 244 finally { 245 close(id); 246 } 247 248 return theData; 249 } 250 251 // Implementing DataFormat 252 /** 253 * Reads the data from file. 254 * 255 * read() reads the data from file to a memory buffer and returns the memory 256 * buffer. The dataset object does not hold the memory buffer. To store the 257 * memory buffer in the dataset object, one must call getData(). 258 * 259 * By default, the whole dataset is read into memory. Users can also select 260 * a subset to read. Subsetting is done in an implicit way. 261 * 262 * @return the data read from file. 263 * 264 * @see #getData() 265 * 266 * @throws HDFException 267 * if object can not be read 268 * @throws OutOfMemoryError 269 * if memory is exhausted 270 */ 271 @SuppressWarnings({"rawtypes", "unchecked", "deprecation"}) 272 @Override 273 public Object read() throws HDFException 274 { 275 List list = null; 276 277 if (!isInited()) 278 init(); 279 280 if (numberOfMembers <= 0) { 281 log.debug("read(): VData contains no members"); 282 return null; // this Vdata does not have any filed 283 } 284 285 long id = open(); 286 if (id < 0) { 287 log.debug("read(): Invalid VData ID"); 288 return null; 289 } 290 291 list = new Vector(); 292 293 // assume external data files are located in the same directory as the main file. 294 HDFLibrary.HXsetdir(getFileFormat().getParent()); 295 296 Object member_data = null; 297 for (int i = 0; i < numberOfMembers; i++) { 298 if (!isMemberSelected[i]) 299 continue; 300 301 try { 302 // moves the access pointer to the start position 303 HDFLibrary.VSseek(id, (int)startDims[0]); 304 // Specify the fields to be accessed 305 HDFLibrary.VSsetfields(id, memberNames[i]); 306 } 307 catch (HDFException ex) { 308 log.debug("read(): failure: ", ex); 309 isMemberSelected[i] = false; 310 continue; 311 } 312 313 int n = memberOrders[i] * (int)selectedDims[0]; 314 315 member_data = H4Datatype.allocateArray(memberTIDs[i], n); 316 317 log.trace("read(): index={} isMemberSelected[i]={} memberOrders[i]={} array size={}", i, 318 isMemberSelected[i], memberOrders[i], n); 319 if (member_data == null) { 320 String[] nullValues = new String[n]; 321 for (int j = 0; j < n; j++) 322 nullValues[j] = "*ERROR*"; 323 list.add(nullValues); 324 continue; 325 } 326 327 try { 328 HDFLibrary.VSread(id, member_data, (int)selectedDims[0], HDFConstants.FULL_INTERLACE); 329 if ((memberTIDs[i] == HDFConstants.DFNT_CHAR) || 330 (memberTIDs[i] == HDFConstants.DFNT_UCHAR8)) { 331 // convert characters to string 332 log.trace("read(): convert characters to string"); 333 member_data = Dataset.byteToString((byte[])member_data, memberOrders[i]); 334 try { 335 memberTypes[i] = new H4Datatype(Datatype.CLASS_STRING, memberOrders[i], 336 Datatype.NATIVE, Datatype.NATIVE); 337 } 338 catch (Exception ex) { 339 log.debug("read(): failed to create datatype for member[{}]: ", i, ex); 340 memberTypes[i] = null; 341 } 342 memberOrders[i] = 1; // one String 343 } 344 else if (H4Datatype.isUnsigned(memberTIDs[i])) { 345 // convert unsigned integer to appropriate Java integer 346 log.trace("read(): convert unsigned integer to appropriate Java integer"); 347 member_data = Dataset.convertFromUnsignedC(member_data); 348 } 349 } 350 catch (HDFException ex) { 351 String[] nullValues = new String[n]; 352 for (int j = 0; j < n; j++) 353 nullValues[j] = "*ERROR*"; 354 list.add(nullValues); 355 continue; 356 } 357 358 list.add(member_data); 359 } // (int i=0; i<numberOfMembers; i++) 360 361 close(id); 362 363 return list; 364 } 365 366 // Implementing DataFormat 367 /** 368 * Writes a memory buffer to the object in the file. 369 * 370 * @param buf 371 * the data to write 372 * 373 * @throws HDFException 374 * if data can not be written 375 */ 376 @Override 377 public void write(Object buf) throws HDFException 378 { 379 // For writing to a vdata, VSsetfields can only be called once, to set 380 // up the fields in a vdata. Once the vdata fields are set, they may 381 // not be changed. Thus, to update some fields of a record after the 382 // first write, the user must read all the fields to a buffer, update 383 // the buffer, then write the entire record back to the vdata. 384 log.trace("write(): disabled"); 385 /* 386 if (buf == null || numberOfMembers <= 0 || !(buf instanceof List)) 387 return; // no data to write 388 389 List list = (List)buf; 390 Object member_data = null; 391 String member_name = null; 392 393 int vid = open(); 394 if (vid < 0) return; 395 396 int idx = 0; 397 for (int i=0; i<numberOfMembers; i++) { 398 if (!isMemberSelected[i]) 399 continue; 400 401 HDFLibrary.VSsetfields(vid, memberNames[i]); 402 403 try { 404 // Specify the fields to be accessed 405 406 // moves the access pointer to the start position 407 HDFLibrary.VSseek(vid, (int)startDims[0]); 408 } 409 catch (HDFException ex) { 410 continue; 411 } 412 413 member_data = list.get(idx++); 414 if (member_data == null) 415 continue; 416 417 if (memberTIDs[i] == HDFConstants.DFNT_CHAR || 418 memberTIDs[i] == HDFConstants.DFNT_UCHAR8) { 419 member_data = Dataset.stringToByte((String[])member_data, memberOrders[i]); 420 } 421 else if (H4Datatype.isUnsigned(memberTIDs[i])) { 422 // convert unsigned integer to appropriate Java integer 423 member_data = Dataset.convertToUnsignedC(member_data); 424 } 425 426 427 int interlace = HDFConstants.NO_INTERLACE; 428 try { 429 int write_num = HDFLibrary.VSwrite( 430 vid, member_data, (int)selectedDims[0], interlace); 431 } 432 catch (HDFException ex) { 433 log.debug("write():", ex); 434 } 435 } // (int i=0; i<numberOfMembers; i++) 436 437 close(vid); 438 */ 439 } 440 441 /** 442 * Converts the data values of this data object to appropriate Java integers if 443 * they are unsigned integers. 444 * 445 * @see hdf.object.Dataset#convertToUnsignedC(Object) 446 * @see hdf.object.Dataset#convertFromUnsignedC(Object, Object) 447 * 448 * @return the converted data buffer. 449 */ 450 @Override 451 public Object convertFromUnsignedC() 452 { 453 throw new UnsupportedOperationException("H4Vdata:convertFromUnsignedC Unsupported operation."); 454 } 455 456 /** 457 * Converts Java integer data values of this data object back to unsigned C-type 458 * integer data if they are unsigned integers. 459 * 460 * @see hdf.object.Dataset#convertToUnsignedC(Object) 461 * @see hdf.object.Dataset#convertToUnsignedC(Object, Object) 462 * 463 * @return the converted data buffer. 464 */ 465 @Override 466 public Object convertToUnsignedC() 467 { 468 throw new UnsupportedOperationException("H4Vdata:convertToUnsignedC Unsupported operation."); 469 } 470 471 // Implementing DataFormat 472 /** 473 * Retrieves the object's metadata, such as attributes, from the file. 474 * 475 * Metadata, such as attributes, is stored in a List. 476 * 477 * @return the list of metadata objects. 478 * 479 * @throws HDFException 480 * if the metadata can not be retrieved 481 */ 482 @Override 483 @SuppressWarnings({"rawtypes", "unchecked"}) 484 public List getMetadata() throws HDFException 485 { 486 if (attributeList != null) { 487 log.trace("getMetdata(): attributeList != null"); 488 return attributeList; 489 } 490 491 long id = open(); 492 493 if (id < 0) { 494 log.debug("getMetadata(): Invalid VData ID"); 495 return attributeList; 496 } 497 498 int n = 0; 499 try { 500 n = HDFLibrary.VSnattrs(id); 501 502 if (n <= 0) { 503 log.debug("getMetadata(): VData number of attributes <= 0"); 504 return attributeList; 505 } 506 507 attributeList = new Vector(n, 5); 508 boolean b = false; 509 String[] attrName = new String[1]; 510 int[] attrInfo = new int[5]; 511 512 // _HDF_VDATA (or -1) to specify the vdata attribute 513 int nleft = n; 514 for (int j = -1; j < numberOfMembers; j++) { 515 for (int i = 0; i < nleft; i++) { 516 attrName[0] = ""; 517 518 try { 519 b = HDFLibrary.VSattrinfo(id, j, i, attrName, attrInfo); 520 // mask off the litend bit 521 attrInfo[0] = attrInfo[0] & (~HDFConstants.DFNT_LITEND); 522 } 523 catch (HDFException ex) { 524 log.debug("getMetadata(): attribute[{}] VSattrinfo failure: ", i, ex); 525 b = false; 526 ex.printStackTrace(); 527 } 528 529 if (!b || attrName[0].length() <= 0) 530 continue; 531 532 long[] attrDims = {attrInfo[1]}; 533 H4CompoundAttribute attr = 534 new H4CompoundAttribute(this, attrName[0], new H4Datatype(attrInfo[0]), attrDims); 535 if (j >= 0) 536 attr.setProperty("field", memberNames[j]); 537 attributeList.add(attr); 538 539 Object buf = null; 540 try { 541 buf = H4Datatype.allocateArray(attrInfo[0], attrInfo[1]); 542 } 543 catch (OutOfMemoryError e) { 544 log.debug("getMetadata(): out of memory: ", e); 545 buf = null; 546 } 547 548 try { 549 HDFLibrary.VSgetattr(id, j, i, buf); 550 } 551 catch (HDFException ex) { 552 log.debug("getMetadata(): attribute[{}] VSgetattr failure: ", i, ex); 553 buf = null; 554 } 555 556 if (buf != null) { 557 if ((attrInfo[0] == HDFConstants.DFNT_CHAR) || 558 (attrInfo[0] == HDFConstants.DFNT_UCHAR8)) { 559 buf = Dataset.byteToString((byte[])buf, attrInfo[1]); 560 } 561 562 attr.setAttributeData(buf); 563 nleft--; 564 } 565 } // (int i=0; i<n; i++) 566 } // (int j=-1; j<numberOfMembers; j++) 567 } 568 catch (Exception ex) { 569 log.debug("getMetadata(): failure: ", ex); 570 } 571 finally { 572 close(id); 573 } 574 575 // todo: We shall also load attributes of fields 576 577 return attributeList; 578 } 579 580 // To do: Implementing DataFormat 581 /** 582 * Writes a specific piece of metadata (such as an attribute) into the file. 583 * 584 * If an HDF(4&5) attribute exists in the file, this method updates its 585 * value. If the attribute does not exist in the file, it creates the 586 * attribute in the file and attaches it to the object. It will fail to 587 * write a new attribute to the object where an attribute with the same name 588 * already exists. To update the value of an existing attribute in the file, 589 * one needs to get the instance of the attribute by getMetadata(), change 590 * its values, then use writeMetadata() to write the value. 591 * 592 * @param info 593 * the metadata to write. 594 * 595 * @throws Exception 596 * if the metadata can not be written 597 */ 598 @Override 599 @SuppressWarnings({"rawtypes", "unchecked"}) 600 public void writeMetadata(Object info) throws Exception 601 { 602 // only attribute metadata is supported. 603 if (!(info instanceof Attribute)) { 604 log.debug("writeMetadata(): Object not an H4Attribute"); 605 return; 606 } 607 608 try { 609 getFileFormat().writeAttribute(this, (H4ScalarAttribute)info, true); 610 611 if (attributeList == null) 612 attributeList = new Vector(); 613 614 attributeList.add(info); 615 nAttributes = attributeList.size(); 616 } 617 catch (Exception ex) { 618 log.trace("writeMetadata(): failure: ", ex); 619 } 620 } 621 622 /** 623 * Deletes an existing piece of metadata from this object. 624 * 625 * @param info 626 * the metadata to delete. 627 * 628 * @throws HDFException 629 * if the metadata can not be removed 630 */ 631 @Override 632 public void removeMetadata(Object info) throws HDFException 633 { 634 log.trace("removeMetadata(): disabled"); 635 } 636 637 /** 638 * Updates an existing piece of metadata attached to this object. 639 * 640 * @param info 641 * the metadata to update. 642 * 643 * @throws Exception 644 * if the metadata can not be updated 645 */ 646 @Override 647 public void updateMetadata(Object info) throws Exception 648 { 649 log.trace("updateMetadata(): disabled"); 650 } 651 652 // Implementing DataFormat 653 @Override 654 public long open() 655 { 656 // try to open with write permission 657 long vsid = -1; 658 try { 659 vsid = HDFLibrary.VSattach(getFID(), (int)oid[1], "w"); 660 } 661 catch (HDFException ex) { 662 log.debug("open(w): VSattach failure: ", ex); 663 vsid = -1; 664 } 665 666 // try to open with read-only permission 667 if (vsid < 0) { 668 try { 669 vsid = HDFLibrary.VSattach(getFID(), (int)oid[1], "r"); 670 } 671 catch (HDFException ex) { 672 log.debug("open(r): VSattach failure: ", ex); 673 vsid = -1; 674 } 675 log.debug("open(r): VSattach vsid: {}", vsid); 676 } 677 678 return vsid; 679 } 680 681 // Implementing DataFormat 682 @Override 683 public void close(long vsid) 684 { 685 try { 686 HDFLibrary.VSdetach(vsid); 687 } 688 catch (Exception ex) { 689 log.debug("close(): VSdetach failure: ", ex); 690 } 691 } 692 693 /** 694 * Initializes the H4Vdata such as dimension sizes of this dataset. 695 */ 696 @Override 697 public void init() 698 { 699 if (inited) { 700 log.trace("init(): Already initialized"); 701 return; // already called. Initialize only once 702 } 703 704 long id = open(); 705 if (id < 0) { 706 log.debug("init(): Invalid VData ID"); 707 return; 708 } 709 710 try { 711 numberOfMembers = HDFLibrary.VFnfields(id); 712 numberOfRecords = HDFLibrary.VSelts(id); 713 } 714 catch (HDFException ex) { 715 numberOfMembers = 0; 716 numberOfRecords = 0; 717 } 718 719 // Still need to get information if there is no record, see bug 1738 720 // if ((numberOfMembers <=0) || (numberOfRecords <= 0)) { 721 // // no table field is defined or no records 722 // close(id); 723 // return; 724 // } 725 726 // a Vdata table is an one dimension array of records. 727 // each record has the same fields 728 rank = 1; 729 dims = new long[1]; 730 dims[0] = numberOfRecords; 731 selectedDims = new long[1]; 732 selectedDims[0] = numberOfRecords; 733 selectedIndex[0] = 0; 734 startDims = new long[1]; 735 startDims[0] = 0; 736 737 memberNames = new String[numberOfMembers]; 738 memberTIDs = new long[numberOfMembers]; 739 memberTypes = new Datatype[numberOfMembers]; 740 memberOrders = new int[numberOfMembers]; 741 isMemberSelected = new boolean[numberOfMembers]; 742 743 try { 744 datatype = new H4Datatype(Datatype.CLASS_COMPOUND, -1, Datatype.NATIVE, Datatype.NATIVE); 745 } 746 catch (Exception ex) { 747 log.debug("init(): failed to create compound datatype for VData"); 748 datatype = null; 749 } 750 751 for (int i = 0; i < numberOfMembers; i++) { 752 isMemberSelected[i] = true; 753 try { 754 memberNames[i] = HDFLibrary.VFfieldname(id, i); 755 memberTIDs[i] = HDFLibrary.VFfieldtype(id, i); 756 try { 757 memberTypes[i] = new H4Datatype(memberTIDs[i]); 758 } 759 catch (Exception ex) { 760 log.debug("init(): failed to create datatype for member[{}]: ", i, ex); 761 memberTypes[i] = null; 762 } 763 // mask off the litend bit 764 memberTIDs[i] = memberTIDs[i] & (~HDFConstants.DFNT_LITEND); 765 memberOrders[i] = HDFLibrary.VFfieldorder(id, i); 766 log.trace( 767 "init():{}> isMemberSelected[i]={} memberNames[i]={} memberTIDs[i]={} memberOrders[i]={}", 768 i, isMemberSelected[i], memberNames[i], memberTIDs[i], memberOrders[i]); 769 770 /* 771 * NOTE: An ugly workaround to get HDF4 "compound" datatypes to work correctly. 772 */ 773 if (datatype != null) { 774 datatype.getCompoundMemberNames().add(memberNames[i]); 775 datatype.getCompoundMemberTypes().add(memberTypes[i]); 776 } 777 } 778 catch (HDFException ex) { 779 log.debug("init(): member[{}]: ", i, ex); 780 continue; 781 } 782 } // (int i=0; i<numberOfMembers; i++) 783 784 inited = true; 785 786 close(id); 787 } 788 789 /** 790 * Returns the number of records. 791 * 792 * @return the number of records 793 */ 794 public int getRecordCount() { return numberOfRecords; } 795 796 /** 797 * Returns the number of fields. 798 * 799 * @return the number of fields 800 */ 801 public int getFieldCount() { return numberOfMembers; } 802 803 /** 804 * Returns the orders of fields 805 * 806 * @return the orders of fields 807 */ 808 public int[] getFieldOrders() { return memberOrders; } 809 810 // Implementing DataFormat 811 /** 812 * Retrieves the object's metadata, such as attributes, from the file. 813 * 814 * Metadata, such as attributes, is stored in a List. 815 * 816 * @param attrPropList 817 * the list of properties to get 818 * 819 * @return the list of metadata objects. 820 * 821 * @throws Exception 822 * if the metadata can not be retrieved 823 */ 824 @SuppressWarnings("rawtypes") 825 public List getMetadata(int... attrPropList) throws Exception 826 { 827 throw new UnsupportedOperationException("getMetadata(int... attrPropList) is not supported"); 828 } 829 830 @Override 831 public Dataset copy(Group pgroup, String name, long[] dims, Object data) throws Exception 832 { 833 throw new UnsupportedOperationException("Writing a vdata to a new dataset is not implemented."); 834 } 835}