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; 016 017import java.io.File; 018import java.util.Enumeration; 019import java.util.Hashtable; 020import java.util.Iterator; 021import java.util.Map; 022import java.util.StringTokenizer; 023import java.util.Vector; 024 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028/** 029 * FileFormat defines general interfaces for working with files whose data is 030 * organized according to a supported format. 031 * 032 * FileFormat is a pluggable component. New implementing classes of FileFormat 033 * can be added to the list of supported file formats. Current implementing 034 * classes include H5File and H4File. By default, H5File and H4File are added to 035 * the list of supported file formats maintained by the static FileFormat 036 * instance. 037 * 038 * <pre> 039 * FileFormat 040 * _________________|_________________ 041 * | | | 042 * H5File H4File Other... 043 * </pre> 044 * 045 * A FileFormat instance may exist without being associated with a given file. A 046 * FileFormat instance may be associated with a file that is not open for 047 * access. Most typically, a FileFormat instance is used to open the associated 048 * file and perform operations such as retrieval and manipulation (if the file 049 * access is read-write) of the file structure and objects. 050 * 051 * @author Peter X. Cao 052 * @version 2.4 9/4/2007 053 */ 054public abstract class FileFormat extends File { 055 private static final long serialVersionUID = -4700692313888420796L; 056 057 private static final Logger log = LoggerFactory.getLogger(FileFormat.class); 058 059 /*************************************************************************** 060 * File access flags used in calls to createInstance( String, flag ); 061 **************************************************************************/ 062 063 /** 064 * File first time access flag for open file. With this access flag, added 065 * to the regular value, indicates this file has no existing state. 066 * 067 */ 068 public static final int OPEN_NEW = 1; 069 070 /** 071 * File access flag for read-only permission. With this access flag, 072 * modifications to the file will not be allowed. 073 * 074 * @see #createInstance(String, int ) 075 */ 076 public static final int READ = 2; 077 078 /** 079 * File access flag for read/write permission. With this access flag, 080 * modifications to the file will be allowed. Behavior if the file does not 081 * exist or cannot be opened for read/write access depends on the 082 * implementing class. 083 * 084 * @see #createInstance(String, int) 085 */ 086 public static final int WRITE = 4; 087 088 /** 089 * File access flag for creating/truncating with read-write permission. If 090 * the file already exists, it will be truncated when opened. With this 091 * access flag, modifications to the file will be allowed. Behavior if file 092 * can't be created, or if it exists but can't be opened for read/write 093 * access, depends on the implementing class. 094 * 095 * @see #createInstance(String, int ) 096 */ 097 public static final int CREATE = 8; 098 099 /** 100 * File access flag for multi-read-only permission. With this access flag, 101 * modifications to the file will not be allowed. 102 * 103 * @see #createInstance(String, int ) 104 */ 105 public static final int MULTIREAD = 80; 106 107 /*************************************************************************** 108 * File creation flags used in calls to createFile( String, flag ); 109 **************************************************************************/ 110 111 /** 112 * Flag for creating/truncating a file. If the file already exists, it will 113 * be truncated when opened. If the file does not exist, it will be created. 114 * Modifications to the file will be allowed. 115 * 116 * @see #createFile(String, int ) 117 */ 118 public static final int FILE_CREATE_DELETE = 10; 119 120 /** 121 * Flag for creating/opening a file. If the file already exists, it will be 122 * opened without changing the existing contents. If the file does not 123 * exist, it will be created. Modifications to the file will be allowed. 124 * 125 * @see #createFile(String, int ) 126 */ 127 public static final int FILE_CREATE_OPEN = 20; 128 129 /** 130 * Flag to indicate if the earliest version of library is used when creating 131 * a new file. 132 * 133 * @see #createFile(String, int ) 134 */ 135 public static final int FILE_CREATE_EARLY_LIB = 40; 136 137 /*************************************************************************** 138 * Keys and fields related to supported file formats. 139 **************************************************************************/ 140 141 /** Key for HDF4 file format. */ 142 public static final String FILE_TYPE_HDF4 = "HDF4"; 143 144 /** Key for HDF5 file format. */ 145 public static final String FILE_TYPE_HDF5 = "HDF5"; 146 147 /** Key for NetCDF file format. */ 148 public static final String FILE_TYPE_NC3 = "NetCDF3"; 149 150 /** 151 * A separator that separates file name and object name. 152 * 153 * @see hdf.object.FileFormat#getHObject(String) 154 */ 155 public static final String FILE_OBJ_SEP = "://"; 156 157 /** 158 * FileList keeps a list of supported FileFormats. This list can be updated 159 * and queried at runtime. 160 * 161 * @see #addFileFormat(String,FileFormat) 162 * @see #getFileFormat(String) 163 * @see #getFileFormatKeys() 164 * @see #getFileFormats() 165 * @see #removeFileFormat(String) 166 */ 167 private static final Map<String, FileFormat> FileList = new Hashtable<>(10); 168 169 /** 170 * A list of file extensions for the supported file formats. This list of 171 * file extensions is not integrated with the supported file formats kept in 172 * FileList, but is provided as a convenience for applications who may 173 * choose to process only those files with recognized extensions. 174 */ 175 private static String extensions = "hdf, h4, hdf5, h5, nc, fits"; 176 177 /*************************************************************************** 178 * Sizing information and class metadata 179 **************************************************************************/ 180 181 /** 182 * Current Java applications, such as HDFView, cannot handle files with 183 * large numbers of objects due to JVM memory limitations. For example, 184 * 1,000,000 objects is too many. max_members is defined so that 185 * applications such as HDFView will load up to <i>max_members</i> objects 186 * starting with the <i>start_members</i> -th object. The implementing class 187 * has freedom in its interpretation of how to "count" objects in the file. 188 */ 189 private int max_members = 10000; // 10,000 by default 190 /** 191 * The start number for max_members . 192 */ 193 private int start_members = 0; // 0 by default 194 195 /** 196 * File identifier. -1 indicates the file is not open. 197 */ 198 protected long fid = -1; 199 200 /** 201 * The absolute pathname (path+name) of the file. 202 */ 203 protected String fullFileName = null; 204 205 /** 206 * Flag indicating if the file access is read-only. 207 */ 208 protected boolean isReadOnly = false; 209 210 /*************************************************************************** 211 * Class initialization method 212 **************************************************************************/ 213 214 /** 215 * By default, HDF4 and HDF5 file formats are added to the supported formats 216 * list. 217 */ 218 static 219 { 220 // add HDF4 to default modules 221 if (FileFormat.getFileFormat(FILE_TYPE_HDF4) == null) { 222 try { 223 @SuppressWarnings("rawtypes") 224 Class fileclass = Class.forName("hdf.object.h4.H4File"); 225 FileFormat fileformat = (FileFormat)fileclass.newInstance(); 226 if (fileformat != null) { 227 FileFormat.addFileFormat(FILE_TYPE_HDF4, fileformat); 228 log.debug("FILE_TYPE_HDF4 file format added"); 229 } 230 } 231 catch (Exception err) { 232 log.debug("FILE_TYPE_HDF4 instance failure: ", err); 233 } 234 } 235 236 // add HDF5 to default modules 237 if (FileFormat.getFileFormat(FILE_TYPE_HDF5) == null) { 238 try { 239 @SuppressWarnings("rawtypes") 240 Class fileclass = Class.forName("hdf.object.h5.H5File"); 241 FileFormat fileformat = (FileFormat)fileclass.newInstance(); 242 if (fileformat != null) { 243 FileFormat.addFileFormat(FILE_TYPE_HDF5, fileformat); 244 log.debug("FILE_TYPE_HDF5 file format added"); 245 } 246 } 247 catch (Exception err) { 248 log.debug("FILE_TYPE_HDF5 instance failure: ", err); 249 } 250 } 251 252 // add NetCDF to default modules 253 if (FileFormat.getFileFormat(FILE_TYPE_NC3) == null) { 254 try { 255 @SuppressWarnings("rawtypes") 256 Class fileclass = Class.forName("hdf.object.nc2.NC2File"); 257 FileFormat fileformat = (FileFormat)fileclass.newInstance(); 258 if (fileformat != null) { 259 FileFormat.addFileFormat(FILE_TYPE_NC3, fileformat); 260 log.debug("NetCDF3 file format added"); 261 } 262 } 263 catch (Exception err) { 264 log.debug("NetCDF3 instance failure: ", err); 265 } 266 } 267 268 // add FITS to default modules 269 if (FileFormat.getFileFormat("FITS") == null) { 270 try { 271 @SuppressWarnings("rawtypes") 272 Class fileclass = Class.forName("hdf.object.fits.FitsFile"); 273 FileFormat fileformat = (FileFormat)fileclass.newInstance(); 274 if (fileformat != null) { 275 FileFormat.addFileFormat("FITS", fileformat); 276 log.debug("Fits file format added"); 277 } 278 } 279 catch (Exception err) { 280 log.debug("FITS instance failure: ", err); 281 } 282 } 283 } 284 285 /*************************************************************************** 286 * Constructor 287 **************************************************************************/ 288 289 /** 290 * Creates a new FileFormat instance with the given filename. 291 * 292 * The filename in this method call is equivalent to the pathname in the 293 * java.io.File class. The filename is converted into an abstract pathname 294 * by the File class. 295 * 296 * Typically this constructor is not called directly, but is called by a 297 * constructor of an implementing class. Applications most frequently use 298 * the <i>createFile()</i>, <i>createInstance()</i>, or <i>getInstance()</i> 299 * methods to generate a FileFormat instance with an associated filename. 300 * 301 * The file is not opened by this call. The read-only flag is set to false 302 * by this call. 303 * 304 * @param filename 305 * The filename; a pathname string. 306 * @throws NullPointerException 307 * If the <code>filename</code> argument is <code>null</code>. 308 * @see java.io.File#File(String) 309 * @see #createFile(String, int) 310 * @see #createInstance(String, int) 311 * @see #getInstance(String) 312 */ 313 public FileFormat(String filename) 314 { 315 super(filename); 316 317 fullFileName = filename; 318 319 if ((filename != null) && (filename.length() > 0)) { 320 try { 321 fullFileName = this.getAbsolutePath(); 322 } 323 catch (Exception ex) { 324 log.debug("File {} getAbsolutePath failure: ", filename, ex); 325 } 326 } 327 isReadOnly = false; 328 log.trace("fullFileName={} isReadOnly={}", fullFileName, isReadOnly); 329 } 330 331 /*************************************************************************** 332 * Class methods 333 **************************************************************************/ 334 335 /** 336 * Adds a FileFormat with specified key to the list of supported formats. 337 * 338 * This method allows a new FileFormat, tagged with an identifying key, to 339 * be added dynamically to the list of supported File Formats. Using it, 340 * applications can add new File Formats at runtime. 341 * 342 * For example, to add a new File Format with the key "xyz" that is 343 * implemented by the class xyzFile in the package companyC.files, an 344 * application would make the following calls: 345 * 346 * <pre> 347 * Class fileClass = Class.forName( "companyC.files.xyzFile" ); 348 * FileFormat ff = (FileFormat) fileClass.newInstance(); 349 * if ( ff != null ) { 350 * ff.addFileFormat ("xyz", ff ) 351 * } 352 * </pre> 353 * 354 * If either <code>key</code> or <code>fileformat</code> are 355 * <code>null</code>, or if <code>key</code> is already in use, the method 356 * returns without updating the list of supported File Formats. 357 * 358 * @param key 359 * A string that identifies the FileFormat. 360 * @param fileformat 361 * An instance of the FileFormat to be added. 362 * @see #getFileFormat(String) 363 * @see #getFileFormatKeys() 364 * @see #getFileFormats() 365 * @see #removeFileFormat(String) 366 */ 367 public static final void addFileFormat(String key, FileFormat fileformat) 368 { 369 if ((fileformat == null) || (key == null)) 370 return; 371 372 key = key.trim(); 373 374 if (!FileList.containsKey(key)) 375 FileList.put(key, fileformat); 376 } 377 378 /** 379 * Returns the FileFormat with specified key from the list of supported 380 * formats. 381 * 382 * This method returns a FileFormat instance, as identified by an 383 * identifying key, from the list of supported File Formats. 384 * 385 * If the specified key is in the list of supported formats, the instance of 386 * the associated FileFormat object is returned. If the specified key is not 387 * in the list of supported formats, <code>null</code> is returned. 388 * 389 * @param key 390 * A string that identifies the FileFormat. 391 * @return The FileFormat that matches the given key, or <code>null</code> 392 * if the key is not found in the list of supported File Formats. 393 * @see #addFileFormat(String,FileFormat) 394 * @see #getFileFormatKeys() 395 * @see #getFileFormats() 396 * @see #removeFileFormat(String) 397 */ 398 public static final FileFormat getFileFormat(String key) { return FileList.get(key); } 399 400 /** 401 * Returns an Enumeration of keys for all supported formats. 402 * 403 * This method returns an Enumeration containing the unique keys (Strings) 404 * for the all File Formats in the list of supported File Formats. 405 * 406 * @return An Enumeration of keys that are in the list of supported formats. 407 * @see #addFileFormat(String,FileFormat) 408 * @see #getFileFormat(String) 409 * @see #getFileFormats() 410 * @see #removeFileFormat(String) 411 */ 412 @SuppressWarnings("rawtypes") 413 public static final Enumeration getFileFormatKeys() 414 { 415 return ((Hashtable)FileList).keys(); 416 } 417 418 /** 419 * Returns an array of supported FileFormat instances. 420 * 421 * This method returns an array of FileFormat instances that appear in the 422 * list of supported File Formats. 423 * 424 * If the list of supported formats is empty, <code>null</code> is returned. 425 * 426 * @return An array of all FileFormat instances in the list of supported 427 * File Formats, or <code>null</code> if the list is empty. 428 * @see #addFileFormat(String,FileFormat) 429 * @see #getFileFormat(String) 430 * @see #getFileFormatKeys() 431 * @see #removeFileFormat(String) 432 */ 433 @SuppressWarnings("rawtypes") 434 public static final FileFormat[] getFileFormats() 435 { 436 int n = FileList.size(); 437 if (n <= 0) 438 return null; 439 440 int i = 0; 441 FileFormat[] fileformats = new FileFormat[n]; 442 Enumeration<?> local_enum = ((Hashtable)FileList).elements(); 443 while (local_enum.hasMoreElements()) 444 fileformats[i++] = (FileFormat)local_enum.nextElement(); 445 446 return fileformats; 447 } 448 449 /** 450 * Removes a FileFormat from the list of supported formats. 451 * 452 * This method removes a FileFormat, as identified by the specified key, 453 * from the list of supported File Formats. 454 * 455 * If the specified key is in the list of supported formats, the instance of 456 * the FileFormat object that is being removed from the list is returned. If 457 * the key is not in the list of supported formats, <code>null</code> is 458 * returned. 459 * 460 * @param key 461 * A string that identifies the FileFormat to be removed. 462 * @return The FileFormat that is removed, or <code>null</code> if the key 463 * is not found in the list of supported File Formats. 464 * @see #addFileFormat(String,FileFormat) 465 * @see #getFileFormat(String) 466 * @see #getFileFormatKeys() 467 * @see #getFileFormats() 468 */ 469 public static final FileFormat removeFileFormat(String key) { return FileList.remove(key); } 470 471 /** 472 * Adds file extension(s) to the list of file extensions for supported file 473 * formats. 474 * 475 * Multiple extensions can be included in the single parameter if they are 476 * separated by commas. 477 * 478 * The list of file extensions updated by this call is not linked with 479 * supported formats that implement FileFormat objects. The file extension 480 * list is maintained for the benefit of applications that may choose to 481 * recognize only those files with extensions that appear in the list of 482 * file extensions for supported file formats. 483 * 484 * By default, the file extensions list includes: "hdf, h4, hdf5, h5" 485 * 486 * @param extension 487 * The file extension(s) to add. 488 * @see #addFileFormat(String,FileFormat) 489 * @see #getFileExtensions() 490 */ 491 public static final void addFileExtension(String extension) 492 { 493 if ((extensions == null) || (extensions.length() <= 0)) 494 extensions = extension; 495 496 StringTokenizer currentExt = new StringTokenizer(extensions, ","); 497 Vector<String> tokens = new Vector<>(currentExt.countTokens() + 5); 498 499 while (currentExt.hasMoreTokens()) 500 tokens.add(currentExt.nextToken().trim().toLowerCase()); 501 502 currentExt = new StringTokenizer(extension, ","); 503 String ext = null; 504 while (currentExt.hasMoreTokens()) { 505 ext = currentExt.nextToken().trim().toLowerCase(); 506 if (tokens.contains(ext)) 507 continue; 508 509 extensions = extensions + ", " + ext; 510 } 511 512 tokens.setSize(0); 513 } 514 515 /** 516 * Returns a list of file extensions for all supported file formats. 517 * 518 * The extensions in the returned String are separates by commas: 519 * "hdf, h4, hdf5, h5" 520 * 521 * It is the responsibility of the application to update the file extension 522 * list using {@link #addFileExtension(String)} when new FileFormat 523 * implementations are added. 524 * 525 * @return A list of file extensions for all supported file formats. 526 * @see #addFileExtension(String) 527 */ 528 public static final String getFileExtensions() { return extensions; } 529 530 /** 531 * Creates a FileFormat instance for the specified file. 532 * 533 * This method checks the list of supported file formats to find one that 534 * matches the format of the specified file. If a match is found, the method 535 * returns an instance of the associated FileFormat object. If no match is 536 * found, <code>null</code> is returned. 537 * 538 * For example, if "test_hdf5.h5" is an HDF5 file, 539 * FileFormat.getInstance("test_hdf5.h5") will return an instance of H5File. 540 * 541 * The file is not opened as part of this call. Read/write file access is 542 * associated with the FileFormat instance if the matching file format 543 * supports read/write access. Some file formats only support read access. 544 * 545 * @param filename 546 * A valid file name, with a relative or absolute path. 547 * @return An instance of the matched FileFormat; <code>null</code> if no 548 * match. 549 * @throws IllegalArgumentException 550 * If the <code>filename</code> argument is <code>null</code> or 551 * does not specify an existing file. 552 * @throws Exception 553 * If there are problems creating the new instance. 554 * @see #createFile(String, int) 555 * @see #createInstance(String, int) 556 * @see #getFileFormats() 557 */ 558 @SuppressWarnings("rawtypes") 559 public static final FileFormat getInstance(String filename) throws Exception 560 { 561 if ((filename == null) || (filename.length() <= 0)) 562 throw new IllegalArgumentException("Invalid file name: " + filename); 563 564 if (!(new File(filename)).exists()) 565 throw new IllegalArgumentException("File " + filename + " does not exist."); 566 567 FileFormat fileFormat = null; 568 FileFormat knownFormat = null; 569 Enumeration<?> elms = ((Hashtable)FileList).elements(); 570 571 while (elms.hasMoreElements()) { 572 knownFormat = (FileFormat)elms.nextElement(); 573 if (knownFormat.isThisType(filename)) { 574 try { 575 fileFormat = knownFormat.createInstance(filename, WRITE); 576 } 577 catch (Exception ex) { 578 log.debug("File {} createInstance failure: ", filename, ex); 579 } 580 break; 581 } 582 } 583 584 return fileFormat; 585 } 586 587 /*************************************************************************** 588 * Implementation Class methods. These methods are related to the 589 * implementing FileFormat class, but not to a particular instance of that 590 * class. Since we can't override class methods (they can only be shadowed 591 * in Java), these are instance methods. 592 * 593 * The non-abstract methods just throw an exception indicating that the 594 * implementing class doesn't support the functionality. 595 **************************************************************************/ 596 597 /** 598 * Returns the version of the library for the implementing FileFormat class. 599 * 600 * The implementing FileFormat classes have freedom in how they obtain or 601 * generate the version number that is returned by this method. The H5File 602 * and H4File implementations query the underlying HDF libraries and return 603 * the reported version numbers. Other implementing classes may generate the 604 * version string directly within the called method. 605 * 606 * @return The library version. 607 */ 608 public abstract String getLibversion(); 609 610 /** 611 * Checks if the class implements the specified FileFormat. 612 * 613 * The Java "instanceof" operation is unable to check if an object is an 614 * instance of a FileFormat that is loaded at runtime. This method provides 615 * the "instanceof" functionality, and works for implementing classes that 616 * are loaded at runtime. 617 * 618 * This method lets applications that only access the abstract object layer 619 * determine the format of a given instance of the abstract class. 620 * 621 * For example, HDFView uses the following code to determine if a file is an 622 * HDF5 file: 623 * 624 * <pre> 625 * FileFormat h5F = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5); 626 * HObject hObject = viewer.getTreeView().getCurrentObject(); 627 * FileFormat thisF = hObject.getFileFormat(); 628 * boolean isH5 = h5F.isThisType(thisF); 629 * </pre> 630 * 631 * @param fileFormat 632 * The FileFormat to be checked. 633 * @return True if this instance implements the specified FileFormat; 634 * otherwise returns false. 635 * @see #isThisType(String) 636 */ 637 public abstract boolean isThisType(FileFormat fileFormat); 638 639 /** 640 * Checks if the implementing FileFormat class matches the format of the 641 * specified file. 642 * 643 * For example, if "test.h5" is an HDF5 file, the first call to isThisType() 644 * in the code fragment shown will return <code>false</code>, and the second 645 * call will return <code>true</code>. 646 * 647 * <pre> 648 * FileFormat ncF = FileFormat.getFileFormat(FileFormat.FILE_TYPE_NC3); 649 * FileFormat h4F = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4); 650 * FileFormat h5F = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5); 651 * boolean isH4 = h4F.isThisType("test.h5"); // false 652 * boolean 653 * isH5 = h5F.isThisType("test.h5"); // true 654 * </pre> 655 * 656 * @param filename 657 * The name of the file to be checked. 658 * @return True if the format of the file matches the format of this 659 * instance; otherwise returns false. 660 * @see #isThisType(FileFormat) 661 */ 662 public abstract boolean isThisType(String filename); 663 664 /** 665 * Creates a file with the specified name and returns a new FileFormat 666 * implementation instance associated with the file. 667 * 668 * This method creates a file whose format is the same as that of the 669 * implementing class. An instance of the FileFormat implementing class is 670 * created and associated with the file. That instance is returned by the 671 * method. 672 * 673 * The filename in this method call is equivalent to the pathname in the 674 * java.io.File class. The filename is converted into an abstract pathname 675 * by the File class. 676 * 677 * A flag controls the behavior if the named file already exists. The flag 678 * values and corresponding behaviors are: 679 * <ul> 680 * <li>FILE_CREATE_DELETE: Create a new file or truncate an existing one. 681 * <li>FILE_CREATE_OPEN: Create a new file or open an existing one. 682 * </ul> 683 * 684 * If the flag is FILE_CREATE_DELETE, the method will create a new file or 685 * truncate an existing file. If the flag is FILE_CREATE_OPEN and the file 686 * does not exist, the method will create a new file. 687 * 688 * This method does not open the file for access, nor does it confirm that 689 * the file can later be opened read/write. The file open is carried out by 690 * the <i>open()</i> call. 691 * 692 * @param filename 693 * The filename; a pathname string. 694 * @param createFlag 695 * The creation flag, which determines behavior when the file 696 * already exists. Acceptable values are 697 * <code>FILE_CREATE_DELETE</code> and 698 * <code>FILE_CREATE_OPEN</code>. 699 * @throws NullPointerException 700 * If the <code>filename</code> argument is <code>null</code>. 701 * @throws UnsupportedOperationException 702 * If the implementing class does not support the file creation operation. 703 * @throws Exception 704 * If the file cannot be created or if the creation flag has an 705 * unexpected value. The exceptions thrown vary depending on the 706 * implementing class. 707 * @see #createInstance(String, int) 708 * @see #getInstance(String) 709 * @see #open() 710 * 711 * @return the FileFormat instance. 712 */ 713 public FileFormat createFile(String filename, int createFlag) throws Exception 714 { 715 // If the implementing subclass doesn't have this method then that 716 // format doesn't support File Creation and we throw an exception. 717 throw new UnsupportedOperationException("FileFormat FileFormat.createFile(...) is not implemented."); 718 } 719 720 /** 721 * Creates a FileFormat implementation instance with specified filename and 722 * access. 723 * 724 * This method creates an instance of the FileFormat implementing class and 725 * sets the filename and file access parameters. 726 * 727 * The filename in this method call is equivalent to the pathname in the 728 * java.io.File class. The filename is converted into an abstract pathname 729 * by the File class. 730 * 731 * The access parameter values and corresponding behaviors at file open: 732 * <ul> 733 * <li>READ: Read-only access. Fail if file doesn't exist. 734 * <li>SWMR: Read-only access. Fail if file doesn't exist. 735 * <li>WRITE: Read/Write access. Behavior if file doesn't exist or can't be 736 * opened for read/write access depends on the implementing class. 737 * <li>CREATE: Read/Write access. Create a new file or truncate an existing 738 * one. Behavior if file can't be created, or if it exists but can't be 739 * opened read/write depends on the implementing class. 740 * </ul> 741 * 742 * Some FileFormat implementing classes may only support READ access and 743 * will use READ regardless of the value specified in the call. Refer to the 744 * implementing class documentation for details. 745 * 746 * This method does not open the file for access, nor does it confirm that 747 * the file can later be opened read/write or created. The file open is 748 * carried out by the <i>open()</i> call. 749 * 750 * Example (without exception handling): 751 * 752 * <pre> 753 * // Request the implementing class of FileFormat: H5File 754 * FileFormat h5file = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5); 755 * 756 * // Create an instance of H5File object with read/write access 757 * H5File test1 = (H5File) h5file.createInstance("test_hdf5.h5", 758 * FileFormat.WRITE); 759 * 760 * // Open the file and load the file structure; file id is returned. 761 * int fid = test1.open(); 762 * </pre> 763 * 764 * @param filename 765 * The filename; a pathname string. 766 * @param access 767 * The file access flag, which determines behavior when file is 768 * opened. Acceptable values are <code> READ, WRITE, </code> and 769 * <code>CREATE</code>. 770 * @throws NullPointerException 771 * If the <code>filename</code> argument is <code>null</code>. 772 * @throws Exception 773 * If the instance cannot be created or if the access flag has 774 * an unexpected value. The exceptions thrown vary depending on 775 * the implementing class. 776 * @see #createFile(String, int) 777 * @see #getInstance(String) 778 * @see #open() 779 * 780 * @return the FileFormat instance. 781 */ 782 public abstract FileFormat createInstance(String filename, int access) throws Exception; 783 784 // REVIEW DOCS for createInstance() 785 // What if READ ONLY in implementation? What if file already open? 786 // Can we doc exceptions better or in implementation methods? 787 788 /*************************************************************************** 789 * Final instance methods 790 * 791 * Related to a given instance of the class, but at the FileFormat level, 792 * not at the implementing class level. 793 **************************************************************************/ 794 795 /** 796 * Returns the absolute path for the file. 797 * 798 * For example, "/samples/hdf5_test.h5". If there is no file associated with 799 * this FileFormat instance, <code>null</code> is returned. 800 * 801 * @return The full path (file path + file name) of the associated file, or 802 * <code>null</code> if there is no associated file. 803 */ 804 public final String getFilePath() { return fullFileName; } 805 806 /** 807 * Returns file identifier of open file associated with this instance. 808 * 809 * @return The file identifer, or -1 if there is no file open. 810 */ 811 public final long getFID() { return fid; } 812 813 /** 814 * Returns true if the file access is read-only. 815 * 816 * This method returns true if the file access is read-only. If the file 817 * access is read-write, or if there is no file associated with the 818 * FileFormat instance, false will be returned. 819 * 820 * Note that this method may return true even if the file is not open for 821 * access when the method is called. The file access is set by the 822 * <i>createFile()</i>, <i>createInstance()</i>, or <i>getInstance()</i> 823 * call, and the file is opened for access by the <i>open()</i> call. 824 * 825 * @return True if the file access is read-only, otherwise returns false. 826 * @see #createFile(String, int) 827 * @see #createInstance(String, int) 828 * @see #getInstance(String) 829 * @see #open() 830 */ 831 public final boolean isReadOnly() { return isReadOnly; } 832 833 /** 834 * Sets the maximum number of objects to be loaded into memory. 835 * 836 * Current Java applications, such as HDFView, cannot handle files with 837 * large numbers of objects due to JVM memory limitations. The maximum 838 * number limits the number of objects that will be loaded for a given 839 * FileFormat instance. 840 * 841 * The implementing FileFormat class has freedom in how it interprets the 842 * maximum number. H5File, for example, will load the maximum number of 843 * objects for each group in the file. 844 * 845 * @param n 846 * The maximum number of objects to be loaded into memory. 847 * @see #getMaxMembers() 848 * @see #setStartMembers(int) 849 */ 850 public final void setMaxMembers(int n) { max_members = n; } 851 852 /** 853 * Returns the maximum number of objects that can be loaded into memory. 854 * 855 * @return The maximum number of objects that can be loaded into memory. 856 * @see #setMaxMembers(int) 857 */ 858 public final int getMaxMembers() 859 { 860 if (max_members < 0) 861 return Integer.MAX_VALUE; // load the whole file 862 863 return max_members; 864 } 865 866 /** 867 * Sets the starting index of objects to be loaded into memory. 868 * 869 * The implementing FileFormat class has freedom in how it indexes objects 870 * in the file. 871 * 872 * @param idx 873 * The starting index of the object to be loaded into memory 874 * @see #getStartMembers() 875 * @see #setMaxMembers(int) 876 */ 877 public final void setStartMembers(int idx) { start_members = idx; } 878 879 /** 880 * Returns the index of the starting object to be loaded into memory. 881 * 882 * @return The index of the starting object to be loaded into memory. 883 * @see #setStartMembers(int) 884 */ 885 public final int getStartMembers() { return start_members; } 886 887 /** 888 * Returns the number of objects in memory. 889 * 890 * This method returns the total number of objects loaded into memory for 891 * this FileFormat instance. The method counts the objects that are loaded, 892 * which can take some time for a large number of objects. 893 * 894 * It is worth noting that the total number of objects in memory may be 895 * different than the total number of objects in the file. 896 * 897 * Since implementing classes have freedom in how they interpret and use the 898 * maximum number of members value, there may be differing numbers of 899 * objects in memory in different implementation instances, even with the 900 * same "use case". 901 * 902 * For example, say the use case is a file that contains 20,000 objects, the 903 * maximum number of members for an instance is 10,000, and the start member 904 * index is 1. There are 2 groups in the file. The root group contains 905 * 10,500 objects and the group "/g1" contains 9,500 objects. 906 * 907 * In an implementation that limits the total number of objects loaded to 908 * the maximum number of members, this method will return 10,000. 909 * 910 * In contrast, the H5File implementation loads up to the maximum number of 911 * members objects for each group in the file. So, with our use case 10,000 912 * objects will be loaded in the root group and 9,500 objects will be loaded 913 * into group "/g1". This method will return the value 19,500, which exceeds 914 * the maximum number of members value. 915 * 916 * @return The number of objects in memory. 917 * @see #getMaxMembers() 918 * @see #setMaxMembers(int) 919 * @see #getStartMembers() 920 * @see #setStartMembers(int) 921 */ 922 public final int getNumberOfMembers() 923 { 924 HObject rootObject = getRootObject(); 925 926 // Account for root object 927 if (rootObject != null) 928 return ((Group)rootObject).depthFirstMemberList().size() + 1; 929 930 return 0; 931 } 932 933 /*************************************************************************** 934 * Abstract Instance methods 935 * 936 * These methods are related to the Implementing FileFormat class and to 937 * particular instances of objects with those classes. 938 **************************************************************************/ 939 940 /** 941 * Opens file and returns a file identifier. 942 * 943 * This method uses the <code>filename</code> and <code>access</code> 944 * parameters specified in the <i>createFile()</i>, <i>createInstance()</i>, 945 * or <i>getInstance()</i> call to open the file. It returns the file 946 * identifier if successful, or a negative value in case of failure. 947 * 948 * The method also loads the file structure and basic information (name, 949 * type) for data objects in the file into the FileFormat instance. It does 950 * not load the contents of any data object. 951 * 952 * The structure of the file is stored in a tree starting from the root 953 * object. 954 * 955 * @return File identifier if successful; otherwise -1. 956 * @throws Exception 957 * If the file cannot be opened. The exceptions thrown vary 958 * depending on the implementing class. 959 * @see #createFile(String, int) 960 * @see #createInstance(String, int) 961 * @see #getInstance(String) 962 * @see #getRootObject() 963 */ 964 public abstract long open() throws Exception; 965 966 /** 967 * Closes file associated with this instance. 968 * 969 * This method closes the file associated with this FileFormat instance, as 970 * well as all objects associated with the file. 971 * 972 * @throws Exception 973 * If the file or associated objects cannot be closed. The 974 * exceptions thrown vary depending on the implementing class. 975 * @see #open() 976 */ 977 public abstract void close() throws Exception; 978 979 // REVIEW DOCS for close() 980 // What if we try to close a file whose fid is -1? Does this set fid to -1? 981 // What if it's not open? What if no file? are structures & root object 982 // still loaded? 983 // Can we doc exceptions better or in implementation methods? 984 985 /** 986 * Returns the root object for the file associated with this instance. 987 * 988 * The root object is an HObject that represents the root group of a 989 * file. If the file has not yet been opened, or if there is no file 990 * associated with this instance, <code>null</code> will be returned. 991 * 992 * Starting from the root, applications can descend through the tree 993 * structure and navigate among the file's objects. In the tree structure, 994 * internal items represent non-empty groups. Leaf items represent datasets, 995 * named datatypes, or empty groups. 996 * 997 * @return The root object of the file, or <code>null</code> if there is no 998 * associated file or if the associated file has not yet been opened. 999 * @see #open() 1000 */ 1001 public abstract HObject getRootObject(); 1002 1003 /** 1004 * Gets the HObject with the specified path from the file. 1005 * 1006 * This method returns the specified object from the file associated with 1007 * this FileFormat instance. 1008 * 1009 * If the specified object is a group, groups and datasets that are members 1010 * of the group will be accessible via the returned HObject instance. The 1011 * exact contents of the returned HObject instance depends on whether or not 1012 * {@link #open()} was called previously for this file. 1013 * <ul> 1014 * <li>If the file was opened prior to this method call, the complete tree 1015 * of objects under the group will be accessible via the returned HObject 1016 * instance. 1017 * <li>If the file was not opened prior to this method call, only the 1018 * members immediately under the group will be accessible via the returned 1019 * HOBject instance. 1020 * </ul> 1021 * 1022 * The decision to have different behaviors was made to give users some 1023 * control over the "cost" of the method. In many cases, a user wants only 1024 * one level of a tree, and the performance penalty for loading the entire 1025 * hierarchy of objects in a large and complex file can be significant. In 1026 * the case where <i>open()</i> has already been called, the HObject 1027 * instances have already been created in memory and can be returned 1028 * quickly. If <i>open()</i> has not been called, this method creates the 1029 * HObject instances before returning the requested HObject. 1030 * 1031 * For example, say we have the following structure in our file: 1032 * 1033 * <pre> 1034 * /g0 Group 1035 * /g0/dataset_comp Dataset {50, 10} 1036 * /g0/dataset_int Dataset {50, 10} 1037 * /g0/g00 Group 1038 * /g0/g00/dataset_float Dataset {50, 10} 1039 * /g0/g01 Group 1040 * /g0/g01/dataset_string Dataset {50, 10} 1041 * </pre> 1042 * 1043 * <ul> 1044 * <li>If <i>open()</i> is called before <i>get()</i>, the full structure of 1045 * file is loaded into memory. The call <code>get("/g0")</code> returns the 1046 * instance for /g0 with the information necessary to access 1047 * /g0/dataset_comp, /g0/dataset_int, /g0/g00, /g0/g00/dataset_float, 1048 * /g0/g01, and /g0/g01/dataset_string. 1049 * <li>If <i>open()</i> is not called before <i>get()</i>, only the objects 1050 * immediately under the specified group are accessible via the returned 1051 * HObject instance. In this example, the call <code>get("/go")</code> 1052 * returns the instance for /g0 with the information necessary to access 1053 * /g0/dataset_comp, /g0/dataset_int, /g0/g00, and /g0/g01. 1054 * </ul> 1055 * 1056 * @param path 1057 * Full path of the data object to be returned. 1058 * @return The object if it exists in the file; otherwise <code>null</code>. 1059 * @throws Exception 1060 * If there are unexpected problems in trying to retrieve the 1061 * object. The exceptions thrown vary depending on the 1062 * implementing class. 1063 */ 1064 public abstract HObject get(String path) throws Exception; 1065 1066 // REVIEW DOCS for get(); What if no file associated w/ instance? 1067 // Look at exceptions. Confirm example. Make sure perf tradeoffs 1068 // documented properly. 1069 1070 /** 1071 * Creates a named datatype in a file. 1072 * 1073 * The following code creates a named datatype in a file. 1074 * 1075 * <pre> 1076 * H5File file = (H5File) h5file.createInstance("test_hdf5.h5", FileFormat.WRITE); 1077 * H5Datatype dtype = file.createNamedDatatype( 1078 * nativetype, 1079 * "Native Integer"); 1080 * </pre> 1081 * @param tnative 1082 * the native datatype of the new datatype 1083 * @param name 1084 * name of the datatype to create, e.g. "Native Integer". 1085 * @return The new datatype if successful; otherwise returns null. 1086 * @throws Exception 1087 * The exceptions thrown vary depending on the implementing class. 1088 */ 1089 public Datatype createNamedDatatype(Datatype tnative, String name) throws Exception 1090 { 1091 // If the implementing subclass doesn't have this method then that 1092 // format doesn't support Named Datatypes and we throw an exception. 1093 throw new UnsupportedOperationException( 1094 "Datatype FileFormat.createNamedDatatype(...) is not implemented."); 1095 } 1096 1097 // REVIEW DOCS for createDatatype(). Check and document exceptions. 1098 1099 /*************************************************************************** 1100 * Methods related to Datatypes and HObjects in the implementing FileFormat. 1101 * 1102 * Strictly speaking, these methods aren't related to FileFormat and the 1103 * actions could be carried out through the HObject and Datatype classes. 1104 * But, in some cases they allow a null input and expect the generated 1105 * object to be of a type that has particular FileFormat. Therefore, we put 1106 * them in the implementing FileFormat class so that we create the proper 1107 * type of HObject... H5Group or H4Group for example. 1108 * 1109 * Here again, if there could be Implementation Class methods we'd use 1110 * those. But, since we can't override class methods (they can only be 1111 * shadowed in Java), these are instance methods. 1112 * 1113 * The non-abstract methods just throw an exception indicating that the 1114 * implementing class doesn't support the functionality. 1115 **************************************************************************/ 1116 1117 /** 1118 * Creates a new datatype in memory. 1119 * 1120 * The following code creates an instance of H5Datatype in memory. 1121 * 1122 * <pre> 1123 * H5File file = (H5File) h5file.createInstance("test_hdf5.h5", FileFormat.WRITE); 1124 * H5Datatype dtype = file.createDatatype( 1125 * Datatype.CLASS_INTEGER, 1126 * 4, 1127 * Datatype.NATIVE, 1128 * Datatype.NATIVE); 1129 * </pre> 1130 * 1131 * @param tclass 1132 * class of datatype, e.g. Datatype.CLASS_INTEGER 1133 * @param tsize 1134 * size of the datatype in bytes, e.g. 4 for 32-bit integer. 1135 * @param torder 1136 * order of the byte endian, e.g. Datatype.ORDER_LE. 1137 * @param tsign 1138 * signed or unsigned of an integer, e.g. Datatype.SIGN_NONE. 1139 * @return The new datatype object if successful; otherwise returns null. 1140 * @throws Exception 1141 * The exceptions thrown vary depending on the implementing 1142 * class. 1143 */ 1144 public abstract Datatype createDatatype(int tclass, int tsize, int torder, int tsign) throws Exception; 1145 1146 /** 1147 * Creates a new datatype in memory. 1148 * 1149 * The following code creates an instance of H5Datatype in memory. 1150 * 1151 * <pre> 1152 * H5File file = (H5File) h5file.createInstance("test_hdf5.h5", FileFormat.WRITE); 1153 * H5Datatype dtype = file.createDatatype( 1154 * Datatype.CLASS_INTEGER, 1155 * 4, 1156 * Datatype.NATIVE, 1157 * Datatype.NATIVE, 1158 * basetype); 1159 * </pre> 1160 * 1161 * @param tclass 1162 * class of datatype, e.g. Datatype.CLASS_INTEGER 1163 * @param tsize 1164 * size of the datatype in bytes, e.g. 4 for 32-bit integer. 1165 * @param torder 1166 * order of the byte endian, e.g. Datatype.ORDER_LE. 1167 * @param tsign 1168 * signed or unsigned of an integer, e.g. Datatype.SIGN_NONE. 1169 * @param tbase 1170 * the base datatype of the new datatype 1171 * @return The new datatype object if successful; otherwise returns null. 1172 * @throws Exception 1173 * The exceptions thrown vary depending on the implementing 1174 * class. 1175 */ 1176 public Datatype createDatatype(int tclass, int tsize, int torder, int tsign, Datatype tbase) 1177 throws Exception 1178 { 1179 // Derived classes must override this function to use base type option 1180 return createDatatype(tclass, tsize, torder, tsign); 1181 } 1182 1183 // REVIEW DOCS for createDatatype(). Check and document exceptions. 1184 1185 /** 1186 * Creates a new dataset in a file with/without chunking/compression. 1187 * 1188 * The following example creates a 2D integer dataset of size 100X50 at the root group in an HDF5 1189 * file. 1190 * 1191 * <pre> 1192 * String name = "2D integer"; 1193 * Group pgroup = (Group) getRootObject(); 1194 * Datatype dtype = new H5Datatype(Datatype.CLASS_INTEGER, // class 1195 * 4, // size in bytes 1196 * Datatype.ORDER_LE, // byte order 1197 * Datatype.SIGN_NONE); // unsigned 1198 * long[] dims = { 100, 50 }; 1199 * long[] maxdims = dims; 1200 * long[] chunks = null; // no 1201 * // chunking 1202 * int gzip = 0; // no compression 1203 * Object data = null; // no initial data values 1204 * Dataset d = (H5File) file.createScalarDS(name, pgroup, dtype, dims, maxdims, chunks, gzip, data); 1205 * </pre> 1206 * 1207 * @param name 1208 * name of the new dataset, e.g. "2D integer" 1209 * @param pgroup 1210 * parent group where the new dataset is created. 1211 * @param type 1212 * datatype of the new dataset. 1213 * @param dims 1214 * dimension sizes of the new dataset, e.g. long[] dims = {100, 50}. 1215 * @param maxdims 1216 * maximum dimension sizes of the new dataset, null if maxdims is the same as dims. 1217 * @param chunks 1218 * chunk sizes of the new dataset, null if no chunking. 1219 * @param gzip 1220 * GZIP compression level (1 to 9), 0 or negative values if no compression. 1221 * @param fillValue 1222 * default value. 1223 * @param data 1224 * data written to the new dataset, null if no data is written to the new dataset. 1225 * 1226 * @return The new dataset if successful; otherwise returns null 1227 * @throws Exception 1228 * The exceptions thrown vary depending on the implementing class. 1229 */ 1230 public abstract Dataset createScalarDS(String name, Group pgroup, Datatype type, long[] dims, 1231 long[] maxdims, long[] chunks, int gzip, Object fillValue, 1232 Object data) throws Exception; 1233 1234 /** 1235 * Creates a new dataset in a file with/without chunking/compression. 1236 * 1237 * @param name 1238 * name of the new dataset, e.g. "2D integer" 1239 * @param pgroup 1240 * parent group where the new dataset is created. 1241 * @param type 1242 * datatype of the new dataset. 1243 * @param dims 1244 * dimension sizes of the new dataset, e.g. long[] dims = {100, 50}. 1245 * @param maxdims 1246 * maximum dimension sizes of the new dataset, null if maxdims is the same as dims. 1247 * @param chunks 1248 * chunk sizes of the new dataset, null if no chunking. 1249 * @param gzip 1250 * GZIP compression level (1 to 9), 0 or negative values if no compression. 1251 * @param data 1252 * data written to the new dataset, null if no data is written to the new dataset. 1253 * 1254 * @return The new dataset if successful; otherwise returns null 1255 * @throws Exception 1256 * The exceptions thrown vary depending on the implementing class. 1257 */ 1258 public Dataset createScalarDS(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, 1259 long[] chunks, int gzip, Object data) throws Exception 1260 { 1261 return createScalarDS(name, pgroup, type, dims, maxdims, chunks, gzip, null, data); 1262 } 1263 1264 // REVIEW DOCS for createScalarDS(). Check and document exceptions. 1265 1266 /** 1267 * Creates a new compound dataset in a file with/without chunking and 1268 * compression. 1269 * 1270 * The following example creates a compressed 2D compound dataset with size 1271 * of 100X50 in a root group. The compound dataset has two members, x and y. 1272 * Member x is an interger, member y is an 1-D float array of size 10. 1273 * 1274 * <pre> 1275 * String name = "2D compound"; 1276 * Group pgroup = (Group) getRootObject(); 1277 * long[] dims = {100, 50}; 1278 * long[] chunks = {1, 50}; 1279 * int gzip = 9; 1280 * String[] memberNames = {"x", "y"}; 1281 * 1282 * Datatype[] memberDatatypes = { 1283 * new H5Datatype(Datatype.CLASS_INTEGER, Datatype.NATIVE, 1284 * Datatype.NATIVE, Datatype.NATIVE) 1285 * new H5Datatype(Datatype.CLASS_FLOAT, Datatype.NATIVE, 1286 * Datatype.NATIVE, Datatype.NATIVE)); 1287 * 1288 * int[] memberSizes = {1, 10}; 1289 * Object data = null; // no initial data values 1290 * Dataset d = (H5File)file.createCompoundDS(name, pgroup, dims, null, 1291 * chunks, gzip, memberNames, memberDatatypes, memberSizes, null); 1292 * </pre> 1293 * 1294 * @param name 1295 * name of the new dataset 1296 * @param pgroup 1297 * parent group where the new dataset is created. 1298 * @param dims 1299 * dimension sizes of the new dataset. 1300 * @param maxdims 1301 * maximum dimension sizes of the new dataset, null if maxdims is 1302 * the same as dims. 1303 * @param chunks 1304 * chunk sizes of the new dataset, null if no chunking. 1305 * @param gzip 1306 * GZIP compression level (1 to 9), 0 or negative values if no 1307 * compression. 1308 * @param memberNames 1309 * names of the members. 1310 * @param memberDatatypes 1311 * datatypes of the members. 1312 * @param memberSizes 1313 * array sizes of the members. 1314 * @param data 1315 * data written to the new dataset, null if no data is written to 1316 * the new dataset. 1317 * 1318 * @return new dataset object if successful; otherwise returns null 1319 * @throws UnsupportedOperationException 1320 * If the implementing class does not support compound datasets. 1321 * @throws Exception 1322 * The exceptions thrown vary depending on the implementing 1323 * class. 1324 */ 1325 public Dataset createCompoundDS(String name, Group pgroup, long[] dims, long[] maxdims, long[] chunks, 1326 int gzip, String[] memberNames, Datatype[] memberDatatypes, 1327 int[] memberSizes, Object data) throws Exception 1328 { 1329 // If the implementing subclass doesn't have this method then that 1330 // format doesn't support Compound DataSets and we throw an 1331 // exception. 1332 throw new UnsupportedOperationException( 1333 "Dataset FileFormat.createCompoundDS(...) is not implemented."); 1334 } 1335 1336 /** 1337 * Creates a new image in a file. 1338 * 1339 * The following example creates a 2D image of size 100X50 in a root group. 1340 * 1341 * <pre> 1342 * String name = "2D image"; 1343 * Group pgroup = (Group) getRootObject(); 1344 * Datatype dtype = new H5Datatype(Datatype.CLASS_INTEGER, 1, Datatype.NATIVE, Datatype.SIGN_NONE); 1345 * long[] dims = {100, 50}; 1346 * long[] maxdims = dims; 1347 * long[] chunks = null; // no chunking 1348 * int gzip = 0; // no compression 1349 * int ncomp = 3; // RGB true color image 1350 * int interlace = ScalarDS.INTERLACE_PIXEL; 1351 * Object data = null; // no initial data values 1352 * Dataset d = (H5File) file.createScalarDS(name, pgroup, dtype, dims, maxdims, chunks, gzip, ncomp, 1353 * interlace, data); 1354 * </pre> 1355 * 1356 * @param name 1357 * name of the new image, "2D image". 1358 * @param pgroup 1359 * parent group where the new image is created. 1360 * @param type 1361 * datatype of the new image. 1362 * @param dims 1363 * dimension sizes of the new dataset, e.g. long[] dims = {100, 1364 * 50}. 1365 * @param maxdims 1366 * maximum dimension sizes of the new dataset, null if maxdims is 1367 * the same as dims. 1368 * @param chunks 1369 * chunk sizes of the new dataset, null if no chunking. 1370 * @param gzip 1371 * GZIP compression level (1 to 9), 0 or negative values if no 1372 * compression. 1373 * @param ncomp 1374 * number of components of the new image, e.g. int ncomp = 3; // 1375 * RGB true color image. 1376 * @param interlace 1377 * interlace mode of the image. Valid values are 1378 * ScalarDS.INTERLACE_PIXEL, ScalarDS.INTERLACE_PLANEL and 1379 * ScalarDS.INTERLACE_LINE. 1380 * @param data 1381 * data value of the image, null if no data. 1382 * 1383 * @return The new image object if successful; otherwise returns null 1384 * 1385 * @throws Exception 1386 * The exceptions thrown vary depending on the implementing 1387 * class. 1388 */ 1389 public abstract Dataset createImage(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, 1390 long[] chunks, int gzip, int ncomp, int interlace, Object data) 1391 throws Exception; 1392 1393 // REVIEW DOCS for createImage(). Check and document exceptions. 1394 1395 /** 1396 * Creates a new group with specified name in existing group. 1397 * 1398 * If the parent group is null, the new group will be created in the root 1399 * group. 1400 * 1401 * @param name 1402 * The name of the new group. 1403 * @param parentGroup 1404 * The parent group, or null. 1405 * 1406 * @return The new group if successful; otherwise returns null. 1407 * 1408 * @throws Exception 1409 * The exceptions thrown vary depending on the implementing 1410 * class. 1411 */ 1412 public abstract Group createGroup(String name, Group parentGroup) throws Exception; 1413 1414 // REVIEW DOCS for createLink(). 1415 // Verify Implementing classes document these and also 1416 // 'do the right thing' if fid is -1, currentObj is non-null, if 1417 // object is null, or the root group then what? document & verify! 1418 1419 /** 1420 * Creates a soft, hard or external link to an existing object in the open file. 1421 * 1422 * If parentGroup is null, the new link is created in the root group. 1423 * 1424 * @param parentGroup 1425 * The group where the link is created. 1426 * @param name 1427 * The name of the link. 1428 * @param currentObj 1429 * The existing object the new link will reference. 1430 * @param type 1431 * The type of link to be created. It can be a hard link, a soft 1432 * link or an external link. 1433 * 1434 * @return The object pointed to by the new link if successful; otherwise 1435 * returns null. 1436 * 1437 * @throws Exception 1438 * The exceptions thrown vary depending on the implementing class. 1439 */ 1440 public HObject createLink(Group parentGroup, String name, HObject currentObj, int type) throws Exception 1441 { 1442 return createLink(parentGroup, name, currentObj); 1443 } 1444 1445 /** 1446 * Creates a soft or external link to an object in a file that does not exist 1447 * at the time the link is created. 1448 * 1449 * @param parentGroup 1450 * The group where the link is created. 1451 * @param name 1452 * The name of the link. 1453 * @param currentObj 1454 * The name of the object the new link will reference. The object 1455 * doesn't have to exist. 1456 * @param type 1457 * The type of link to be created. 1458 * 1459 * @return The H5Link object pointed to by the new link if successful; 1460 * otherwise returns null. 1461 * 1462 * @throws Exception 1463 * The exceptions thrown vary depending on the implementing class. 1464 */ 1465 public HObject createLink(Group parentGroup, String name, String currentObj, int type) throws Exception 1466 { 1467 return createLink(parentGroup, name, currentObj); 1468 } 1469 1470 /** 1471 * Copies the source object to a new destination. 1472 * 1473 * This method copies the source object to a destination group, and assigns 1474 * the specified name to the new object. 1475 * 1476 * The copy may take place within a single file or across files. If the source 1477 * object and destination group are in different files, the files must have 1478 * the same file format (both HDF5 for example). 1479 * 1480 * The source object can be a group, a dataset, or a named datatype. This 1481 * method copies the object along with all of its attributes and other 1482 * properties. If the source object is a group, this method also copies all 1483 * objects and sub-groups below the group. 1484 * 1485 * The following example shows how to use the copy method to create two 1486 * copies of an existing HDF5 file structure in a new HDF5 file. One copy 1487 * will be under /copy1 and the other under /copy2 in the new file. 1488 * 1489 * <pre> 1490 * // Open the existing file with the source object. 1491 * H5File existingFile = new H5File("existingFile.h5", FileFormat.READ); 1492 * existingFile.open(); 1493 * // Our source object will be the root group. 1494 * HObject srcObj = existingFile.get("/"); 1495 * // Create a new file. 1496 * H5File newFile = new H5File("newFile.h5", FileFormat.CREATE); 1497 * newFile.open(); 1498 * // Both copies in the new file will have the root group as their 1499 * // destination group. 1500 * Group dstGroup = (Group) newFile.get("/"); 1501 * // First copy goes to "/copy1" and second goes to "/copy2". 1502 * // Notice that we can use either H5File instance to perform the copy. 1503 * HObject copy1 = existingFile.copy(srcObj, dstGroup, "copy1"); 1504 * HObject copy2 = newFile.copy(srcObj, dstGroup, "copy2"); 1505 * // Close both the files. 1506 * file.close(); 1507 * newFile.close(); 1508 * </pre> 1509 * 1510 * @param srcObj 1511 * The object to copy. 1512 * @param dstGroup 1513 * The destination group for the new object. 1514 * @param dstName 1515 * The name of the new object. If dstName is null, the name of 1516 * srcObj will be used. 1517 * 1518 * @return The new object, or null if the copy fails. 1519 * 1520 * @throws Exception 1521 * are specific to the implementing class. 1522 */ 1523 public abstract HObject copy(HObject srcObj, Group dstGroup, String dstName) throws Exception; 1524 1525 /** 1526 * Deletes an object from a file. 1527 * 1528 * @param obj 1529 * The object to delete. 1530 * @throws Exception 1531 * The exceptions thrown vary depending on the implementing class. 1532 */ 1533 public abstract void delete(HObject obj)throws Exception; 1534 1535 // REVIEW DOCS for delete(). Check and document exceptions. 1536 1537 /** 1538 * Attaches a given attribute to an object. 1539 * 1540 * If an HDF(4&5) attribute exists in file, the method updates its value. If 1541 * the attribute does not exist in file, it creates the attribute in file 1542 * and attaches it to the object. It will fail to write a new attribute to 1543 * the object where an attribute with the same name already exists. To 1544 * update the value of an existing attribute in file, one needs to get the 1545 * instance of the attribute by getMetadata(), change its values, and use 1546 * writeAttribute() to write the value. 1547 * 1548 * @param obj 1549 * The object to which the attribute is attached to. 1550 * @param attr 1551 * The atribute to attach. 1552 * @param attrExisted 1553 * The indicator if the given attribute exists. 1554 * 1555 * @throws Exception 1556 * The exceptions thrown vary depending on the implementing class. 1557 */ 1558 public abstract void writeAttribute(HObject obj, Attribute attr, boolean attrExisted) throws Exception; 1559 1560 // REVIEW DOCS for writeAttribute(). Check and document exceptions. 1561 1562 /*************************************************************************** 1563 * Deprecated methods. 1564 **************************************************************************/ 1565 1566 /** 1567 * @deprecated As of 2.4, replaced by {@link #createFile(String, int)} 1568 * 1569 * The replacement method has an additional parameter that 1570 * controls the behavior if the file already exists. Use 1571 * <code>FileFormat.FILE_CREATE_DELETE</code> as the second 1572 * argument in the replacement method to mimic the behavior 1573 * originally provided by this method. 1574 * 1575 * @param fileName 1576 * The filename; a pathname string. 1577 * 1578 * @return the created file object 1579 * 1580 * @throws Exception if file cannot be created 1581 */ 1582 @Deprecated 1583 public final FileFormat create(String fileName) throws Exception 1584 { 1585 return createFile(fileName, FileFormat.FILE_CREATE_DELETE); 1586 } 1587 1588 /** 1589 * @deprecated As of 2.4, replaced by {@link #createInstance(String, int)} 1590 * 1591 * The replacement method has identical functionality and a more 1592 * descriptive name. Since <i>open</i> is used elsewhere to 1593 * perform a different function this method has been deprecated. 1594 * 1595 * @param pathname 1596 * The pathname string. 1597 * @param access 1598 * The file access properties 1599 * 1600 * @return the opened file object 1601 * 1602 * @throws Exception if the file cannot be opened 1603 */ 1604 @Deprecated 1605 public final FileFormat open(String pathname, int access) throws Exception 1606 { 1607 return createInstance(pathname, access); 1608 } 1609 1610 /** 1611 * @deprecated As of 2.4, replaced by 1612 * {@link #createCompoundDS(String, Group, long[], long[], long[], int, String[], Datatype[], 1613 * int[], Object)} 1614 * 1615 * The replacement method has additional parameters: 1616 * <code>maxdims, chunks,</code> and <code>gzip</code>. To mimic 1617 * the behavior originally provided by this method, call the 1618 * replacement method with the following parameter list: 1619 * <code> ( name, pgroup, dims, null, null, -1, 1620 * memberNames, memberDatatypes, memberSizes, data ); </code> 1621 * 1622 * @param name 1623 * The dataset name. 1624 * @param pgroup 1625 * The dataset parent. 1626 * @param dims 1627 * The dataset dimensions. 1628 * @param memberNames 1629 * The dataset compound member names. 1630 * @param memberDatatypes 1631 * The dataset compound member datatypes. 1632 * @param memberSizes 1633 * The dataset compound member sizes. 1634 * @param data 1635 * The dataset data. 1636 * 1637 * @return 1638 * The dataset created. 1639 * 1640 * @throws Exception if the dataset cannot be created 1641 */ 1642 @Deprecated 1643 public final Dataset createCompoundDS(String name, Group pgroup, long[] dims, String[] memberNames, 1644 Datatype[] memberDatatypes, int[] memberSizes, Object data) 1645 throws Exception 1646 { 1647 return createCompoundDS(name, pgroup, dims, null, null, -1, memberNames, memberDatatypes, memberSizes, 1648 data); 1649 } 1650 1651 /** 1652 * @deprecated As of 2.4, replaced by {@link #copy(HObject, Group, String)} 1653 * 1654 * To mimic the behavior originally provided by this method, 1655 * call the replacement method with <code>null</code> as the 3rd parameter. 1656 * 1657 * @param srcObj 1658 * The object to be copied 1659 * @param dstGroup 1660 * The group to contain the copied object 1661 * 1662 * @return the copied object 1663 * 1664 * @throws Exception if object can not be copied 1665 */ 1666 @Deprecated 1667 public final HObject copy(HObject srcObj, Group dstGroup) throws Exception 1668 { 1669 return copy(srcObj, dstGroup, null); 1670 } 1671 1672 /** 1673 * @deprecated As of 2.4, replaced by {@link #get(String)} 1674 * 1675 * This static method, which as been deprecated, causes two problems: 1676 * <ul> 1677 * <li>It can be very expensive if it is called many times or in 1678 * a loop because each call to the method creates an instance of a file. 1679 * <li>Since the method does not return the instance of the 1680 * file, the file cannot be closed directly and may be left open 1681 * (memory leak). The only way to close the file is through the 1682 * object returned by this method. 1683 * </ul> 1684 * 1685 * @param fullPath 1686 * The file path string. 1687 * 1688 * @return the object that has the given full path 1689 * 1690 * @throws Exception if the object can not be found 1691 */ 1692 @Deprecated 1693 public static final HObject getHObject(String fullPath) throws Exception 1694 { 1695 if ((fullPath == null) || (fullPath.length() <= 0)) 1696 return null; 1697 1698 String filename = null, path = null; 1699 int idx = fullPath.indexOf(FILE_OBJ_SEP); 1700 1701 if (idx > 0) { 1702 filename = fullPath.substring(0, idx); 1703 path = fullPath.substring(idx + FILE_OBJ_SEP.length()); 1704 if ((path == null) || (path.length() == 0)) 1705 path = "/"; 1706 } 1707 else { 1708 filename = fullPath; 1709 path = "/"; 1710 } 1711 1712 return FileFormat.getHObject(filename, path); 1713 }; 1714 1715 /** 1716 * @deprecated As of 2.4, replaced by {@link #get(String)} 1717 * 1718 * This static method, which as been deprecated, causes two problems: 1719 * <ul> 1720 * <li>It can be very expensive if it is called many times or in 1721 * a loop because each call to the method creates an instance of 1722 * a file. 1723 * <li>Since the method does not return the instance of the 1724 * file, the file cannot be closed directly and may be left open 1725 * (memory leak). The only way to close the file is through the 1726 * object returned by this method, for example: 1727 * <pre> 1728 * Dataset dset = H5File.getObject("hdf5_test.h5", "/images/iceburg"); 1729 * ... 1730 * // close the file through dset 1731 * dset.getFileFormat().close(); 1732 * </pre> 1733 * 1734 * </li> 1735 * </ul> 1736 * 1737 * @param filename 1738 * The filename string. 1739 * @param path 1740 * The path of the file 1741 * 1742 * @return the object that has the given filename and path returns null 1743 * 1744 * @throws Exception if the object can not be found 1745 */ 1746 @Deprecated 1747 public static final HObject getHObject(String filename, String path) throws Exception 1748 { 1749 if ((filename == null) || (filename.length() <= 0)) 1750 throw new IllegalArgumentException("Invalid file name. " + filename); 1751 1752 if (!(new File(filename)).exists()) 1753 throw new IllegalArgumentException("File does not exists"); 1754 1755 HObject obj = null; 1756 FileFormat file = FileFormat.getInstance(filename); 1757 1758 if (file != null) { 1759 obj = file.get(path); 1760 if (obj == null) 1761 file.close(); 1762 } 1763 1764 return obj; 1765 } 1766 1767 /** 1768 * Finds an object by its object ID 1769 * 1770 * @param file 1771 * the file containing the object 1772 * @param oid 1773 * the oid to search for 1774 * 1775 * @return the object that has the given OID; otherwise returns null 1776 */ 1777 public static final HObject findObject(FileFormat file, long[] oid) 1778 { 1779 if ((file == null) || (oid == null)) { 1780 log.debug("findObject(): file is null or oid is null"); 1781 return null; 1782 } 1783 1784 HObject theObj = null; 1785 1786 HObject theRoot = file.getRootObject(); 1787 if (theRoot == null) { 1788 log.debug("findObject(): rootObject is null"); 1789 return null; 1790 } 1791 1792 Iterator<HObject> member_it = ((Group)theRoot).breadthFirstMemberList().iterator(); 1793 while (member_it.hasNext()) { 1794 theObj = member_it.next(); 1795 if (theObj.equalsOID(oid)) 1796 break; 1797 } 1798 1799 return theObj; 1800 } 1801 1802 /** 1803 * Finds an object by the full path of the object (path+name) 1804 * 1805 * @param file 1806 * the file containing the object 1807 * @param path 1808 * the full path of the object to search for 1809 * 1810 * @return the object that has the given path; otherwise returns null 1811 */ 1812 public static final HObject findObject(FileFormat file, String path) 1813 { 1814 log.trace("findObject({}): start", path); 1815 1816 if ((file == null) || (path == null)) { 1817 log.debug("findObject(): file is null or path is null"); 1818 return null; 1819 } 1820 1821 if (!path.endsWith("/")) 1822 path = path + "/"; 1823 1824 HObject theRoot = file.getRootObject(); 1825 1826 if (theRoot == null) { 1827 log.debug("findObject(): rootObject is null"); 1828 return null; 1829 } 1830 else if (path.equals("/")) { 1831 log.debug("findObject() path is rootObject"); 1832 return theRoot; 1833 } 1834 1835 Iterator<HObject> member_it = ((Group)theRoot).breadthFirstMemberList().iterator(); 1836 HObject theObj = null; 1837 while (member_it.hasNext()) { 1838 theObj = member_it.next(); 1839 String fullPath = theObj.getFullName() + "/"; 1840 1841 if (path.equals(fullPath) && theObj.getPath() != null) 1842 break; 1843 else 1844 theObj = null; 1845 } 1846 1847 return theObj; 1848 } 1849 1850 // //////////////////////////////////////////////////////////////////////////////////// 1851 // Added to support HDF5 1.8 features // 1852 // //////////////////////////////////////////////////////////////////////////////////// 1853 1854 /** 1855 * Opens file and returns a file identifier. 1856 * 1857 * @param indexList 1858 * The property list is the list of parameters, like index type 1859 * and the index order. The index type can be alphabetical or 1860 * creation. The index order can be increasing order or 1861 * decreasing order. 1862 * 1863 * @return File identifier if successful; otherwise -1. 1864 * 1865 * @throws Exception 1866 * The exceptions thrown vary depending on the implementing class. 1867 */ 1868 public long open(int... indexList) throws Exception 1869 { 1870 throw new UnsupportedOperationException( 1871 "Unsupported operation. Subclasses must implement FileFormat:open."); 1872 } 1873 1874 /** 1875 * Creates a new group with specified name in existing group. 1876 * 1877 * If the parent group is null, the new group will be created in the root 1878 * group. 1879 * 1880 * @param name 1881 * The name of a new group. 1882 * @param pgroup 1883 * The parent group object. 1884 * @param gplist 1885 * The group creation properties, in which the order of the 1886 * properties conforms the HDF5 library API, H5Gcreate(), i.e. 1887 * lcpl, gcpl and gapl, where 1888 * <ul> 1889 * <li>lcpl : Property list for link creation <li>gcpl : Property 1890 * list for group creation <li>gapl : Property list for group access 1891 * </ul> 1892 * 1893 * @return The new group if successful; otherwise returns null. 1894 * 1895 * @throws Exception 1896 * The exceptions thrown vary depending on the implementing class. 1897 */ 1898 public Group createGroup(String name, Group pgroup, long... gplist) throws Exception 1899 { 1900 throw new UnsupportedOperationException( 1901 "Unsupported operation. Subclasses must implement FileFormat:createGroup."); 1902 } 1903 1904 /*** 1905 * Creates the group creation property list identifier, gcpl. This 1906 * identifier is used when creating Groups. 1907 * 1908 * @param creationorder 1909 * The order in which the objects in a group should be created. 1910 * It can be Tracked or Indexed. 1911 * @param maxcompact 1912 * The maximum number of links to store in the group in a compact format. 1913 * @param mindense 1914 * The minimum number of links to store in the indexed 1915 * format.Groups which are in indexed format and in which the 1916 * number of links falls below this threshold are automatically 1917 * converted to compact format. 1918 * 1919 * @return The gcpl identifier. 1920 * 1921 * @throws Exception 1922 * The exceptions thrown vary depending on the implementing class. 1923 */ 1924 public long createGcpl(int creationorder, int maxcompact, int mindense) throws Exception 1925 { 1926 throw new UnsupportedOperationException( 1927 "Unsupported operation. Subclasses must implement FileFormat:createGcpl."); 1928 } 1929 1930 /** 1931 * Creates a link to an existing object in the open file. 1932 * 1933 * If linkGroup is null, the new link is created in the root group. 1934 * 1935 * @param linkGroup 1936 * The group where the link is created. 1937 * @param name 1938 * The name of the link. 1939 * @param currentObj 1940 * The existing object the new link will reference. 1941 * 1942 * @return The object pointed to by the new link if successful; 1943 * otherwise returns null. 1944 * 1945 * @throws Exception 1946 * The exceptions thrown vary depending on the implementing class. 1947 */ 1948 public HObject createLink(Group linkGroup, String name, Object currentObj) throws Exception 1949 { 1950 throw new UnsupportedOperationException( 1951 "Unsupported operation. Subclasses must implement FileFormat:createLink."); 1952 } 1953 1954 /** 1955 * Export dataset. 1956 * 1957 * @param file_export_name 1958 * The file name to export data into. 1959 * @param object 1960 * The HDF5 dataset object. 1961 * @param binary_order 1962 * The data byte order 1963 * 1964 * @throws Exception 1965 * The exceptions thrown vary depending on the implementing class. 1966 */ 1967 public void exportDataset(String file_export_name, Dataset object, int binary_order) throws Exception 1968 { 1969 throw new UnsupportedOperationException( 1970 "Unsupported operation. Subclasses must implement FileFormat:exportDataset."); 1971 } 1972 1973 /** 1974 * Renames an attribute. 1975 * 1976 * @param obj 1977 * The object whose attribute is to be renamed. 1978 * @param oldAttrName 1979 * The current name of the attribute. 1980 * @param newAttrName 1981 * The new name of the attribute. 1982 * 1983 * @throws Exception 1984 * The exceptions thrown vary depending on the implementing class. 1985 */ 1986 public void renameAttribute(HObject obj, String oldAttrName, String newAttrName) throws Exception 1987 { 1988 throw new UnsupportedOperationException( 1989 "Unsupported operation. Subclasses must implement FileFormat:renameAttribute."); 1990 } 1991 1992 /** 1993 * Sets the bounds of new library versions. 1994 * 1995 * @param lowStr 1996 * The earliest version of the library. 1997 * @param highStr 1998 * The latest version of the library. 1999 * 2000 * @throws Exception 2001 * The exceptions thrown vary depending on the implementing class. 2002 */ 2003 public void setNewLibBounds(String lowStr, String highStr) throws Exception 2004 { 2005 throw new UnsupportedOperationException( 2006 "Unsupported operation. Subclasses must implement FileFormat:setNewLibBounds."); 2007 } 2008 2009 /** 2010 * Sets the bounds of library versions. 2011 * 2012 * @param lowStr 2013 * The earliest version of the library. 2014 * @param highStr 2015 * The latest version of the library. 2016 * 2017 * @throws Exception 2018 * The exceptions thrown vary depending on the implementing class. 2019 */ 2020 public void setLibBounds(String lowStr, String highStr) throws Exception 2021 { 2022 throw new UnsupportedOperationException( 2023 "Unsupported operation. Subclasses must implement FileFormat:setLibBounds."); 2024 } 2025 2026 /** 2027 * Gets the bounds of library versions 2028 * 2029 * @return The earliest and latest library versions in an int array. 2030 * 2031 * @throws Exception 2032 * The exceptions thrown vary depending on the implementing class. 2033 */ 2034 public int[] getLibBounds() throws Exception 2035 { 2036 throw new UnsupportedOperationException( 2037 "Unsupported operation. Subclasses must implement FileFormat:getLibBounds."); 2038 } 2039 2040 /** 2041 * Initialize the bounds of library versions 2042 * 2043 * @throws Exception 2044 * The exceptions thrown vary depending on the implementing class. 2045 */ 2046 public void initLibBounds() throws Exception 2047 { 2048 throw new UnsupportedOperationException( 2049 "Unsupported operation. Subclasses must implement FileFormat:initLibBounds."); 2050 } 2051 2052 /** 2053 * Gets the bounds of library versions as text. 2054 * 2055 * @return libversion The earliest and latest version of the library. 2056 * 2057 * @throws Exception 2058 * The exceptions thrown vary depending on the implementing class. 2059 */ 2060 public String getLibBoundsDescription() throws Exception 2061 { 2062 throw new UnsupportedOperationException( 2063 "Unsupported operation. Subclasses must implement FileFormat:getLibBoundsDescription."); 2064 } 2065 2066 /** 2067 * Get the value of the index type value. 2068 * 2069 * @param strtype The name of the index type. 2070 * 2071 * @return the int value of the index type value. 2072 * 2073 * @throws Exception The exceptions thrown vary depending on the implementing class. 2074 */ 2075 public static int getIndexTypeValue(String strtype) throws Exception 2076 { 2077 throw new UnsupportedOperationException( 2078 "Unsupported operation. Subclasses must implement FileFormat:getIndexTypeValue."); 2079 } 2080 2081 /** 2082 * Get the value of the index type. 2083 * 2084 * @param strtype The name of the index type. 2085 * 2086 * @return the int value of the index type. 2087 * 2088 * @throws Exception The exceptions thrown vary depending on the implementing class. 2089 */ 2090 public int getIndexType(String strtype) throws Exception 2091 { 2092 throw new UnsupportedOperationException( 2093 "Unsupported operation. Subclasses must implement FileFormat:getIndexType."); 2094 } 2095 2096 /** 2097 * set the int value of the index type. 2098 * 2099 * @param indexType 2100 * The value of the index type. 2101 * 2102 * @throws Exception 2103 * The exceptions thrown vary depending on the implementing class. 2104 */ 2105 public void setIndexType(int indexType) throws Exception 2106 { 2107 throw new UnsupportedOperationException( 2108 "Unsupported operation. Subclasses must implement FileFormat:setIndexType."); 2109 } 2110 2111 /** 2112 * Get the value of the index order value. 2113 * 2114 * @param strorder The name of the index order. 2115 * 2116 * @return the int value of the index order value. 2117 * 2118 * @throws Exception The exceptions thrown vary depending on the implementing class. 2119 */ 2120 public static int getIndexOrderValue(String strorder) throws Exception 2121 { 2122 throw new UnsupportedOperationException( 2123 "Unsupported operation. Subclasses must implement FileFormat:getIndexOrderValue."); 2124 } 2125 2126 /** 2127 * Get the value of the index order. 2128 * 2129 * @param strorder The name of the index order. 2130 * 2131 * @return the int value of the index order. 2132 * 2133 * @throws Exception The exceptions thrown vary depending on the implementing class. 2134 */ 2135 public int getIndexOrder(String strorder) throws Exception 2136 { 2137 throw new UnsupportedOperationException( 2138 "Unsupported operation. Subclasses must implement FileFormat:getIndexOrder."); 2139 } 2140 2141 /** 2142 * set the int value of the index order. 2143 * 2144 * @param indexOrder 2145 * The index order. 2146 * 2147 * @throws Exception 2148 * The exceptions thrown vary depending on the implementing class. 2149 */ 2150 public void setIndexOrder(int indexOrder) throws Exception 2151 { 2152 throw new UnsupportedOperationException( 2153 "Unsupported operation. Subclasses must implement FileFormat:setIndexOrder."); 2154 } 2155}