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.fits; 016 017import java.io.DataInput; 018import java.io.IOException; 019import java.io.InputStream; 020import java.io.RandomAccessFile; 021 022import hdf.object.Attribute; 023import hdf.object.Dataset; 024import hdf.object.Datatype; 025import hdf.object.FileFormat; 026import hdf.object.Group; 027import hdf.object.HObject; 028 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import nom.tam.fits.AsciiTableHDU; 033import nom.tam.fits.BasicHDU; 034import nom.tam.fits.BinaryTableHDU; 035import nom.tam.fits.Fits; 036import nom.tam.fits.ImageHDU; 037import nom.tam.fits.RandomGroupsHDU; 038import nom.tam.fits.TableHDU; 039 040/** 041 * This class provides file level APIs. File access APIs include retrieving the 042 * file hierarchy, opening and closing file, and writing file content to disk. 043 * 044 * @version 2.4 9/4/2007 045 * @author Peter X. Cao 046 */ 047public class FitsFile extends FileFormat { 048 private static final long serialVersionUID = -1965689032980605791L; 049 050 private static final Logger log = LoggerFactory.getLogger(FitsFile.class); 051 052 /** 053 * The root object of the file hierarchy. 054 */ 055 private HObject rootObject; 056 057 /** the fits file */ 058 private Fits fitsFile; 059 060 private static boolean isFileOpen; 061 062 /** 063 * Constructs an empty FitsFile with read-only access. 064 */ 065 public FitsFile() { this(""); } 066 067 /** 068 * Constructs an FitsFile object of given file name with read-only access. 069 * 070 * @param pathname the file name. 071 */ 072 public FitsFile(String pathname) 073 { 074 super(pathname); 075 076 isReadOnly = true; 077 isFileOpen = false; 078 this.fid = -1; 079 try { 080 fitsFile = new Fits(fullFileName); 081 } 082 catch (Exception ex) { 083 if (!pathname.isEmpty()) 084 log.debug("Fits({}):", fullFileName, ex); 085 } 086 } 087 088 /** 089 * Checks if the given file format is a Fits file. 090 * 091 * @param fileformat the fileformat to be checked. 092 * 093 * @return true if the given file is an Fits file; otherwise returns false. 094 */ 095 @Override 096 public boolean isThisType(FileFormat fileformat) 097 { 098 return (fileformat instanceof FitsFile); 099 } 100 101 /** 102 * Checks if a given file is a Fits file. 103 * 104 * @param filename the file to be checked. 105 * 106 * @return true if the given file is an Fits file; otherwise returns false. 107 */ 108 @Override 109 public boolean isThisType(String filename) 110 { 111 boolean is_fits = false; 112 RandomAccessFile raf = null; 113 try { 114 raf = new RandomAccessFile(filename, "r"); 115 } 116 catch (Exception ex) { 117 raf = null; 118 } 119 120 if (raf == null) 121 return false; 122 123 byte[] header = new byte[80]; 124 try { 125 raf.read(header); 126 } 127 catch (Exception ex) { 128 header = null; 129 } 130 131 if (header != null) { 132 String front = new String(header, 0, 9); 133 if (!front.startsWith("SIMPLE =")) { 134 try { 135 raf.close(); 136 } 137 catch (Exception ex) { 138 log.debug("closing RandomAccessFile({}):", filename, ex); 139 } 140 return false; 141 } 142 143 String back = new String(header, 9, 70); 144 back = back.trim(); 145 if ((back.length() < 1) || (back.charAt(0) != 'T')) { 146 try { 147 raf.close(); 148 } 149 catch (Exception ex) { 150 log.debug("closing RandomAccessFile({}):", filename, ex); 151 } 152 return false; 153 } 154 155 is_fits = true; 156 ; 157 } 158 159 try { 160 raf.close(); 161 } 162 catch (Exception ex) { 163 log.debug("closing RandomAccessFile({}):", filename, ex); 164 } 165 166 return is_fits; 167 } 168 169 /** 170 * Creates a FitsFile instance with specified file name and READ access. 171 * 172 * @param filename the full path name of the file. 173 * @param access the access properties of the file. 174 * Regardless of specified access, the FitsFile implementation uses* READ. 175 * 176 * @return the Fits file. 177 * 178 * @throws Exception 179 * The exception thrown from the File class. 180 */ 181 @Override 182 public FileFormat createInstance(String filename, int access) throws Exception 183 { 184 return new FitsFile(filename); 185 } 186 187 // Implementing FileFormat 188 @Override 189 public long open() throws Exception 190 { 191 if (!isFileOpen) { 192 isFileOpen = true; 193 rootObject = loadTree(); 194 } 195 196 return 0; 197 } 198 199 private HObject loadTree() 200 { 201 long[] oid = {0}; 202 // root object does not have a parent path or a parent node 203 FitsGroup rootGroup = new FitsGroup(this, "/", null, null, oid); 204 205 if (fitsFile == null) 206 return rootGroup; 207 208 BasicHDU[] hdus = null; 209 210 try { 211 hdus = fitsFile.read(); 212 } 213 catch (Exception ex) { 214 log.debug("fitsFile.read():", ex); 215 } 216 217 if (hdus == null) 218 return rootGroup; 219 220 int n = hdus.length; 221 int nImageHDU = 0; 222 int nTableHDU = 0; 223 String hduName = null; 224 BasicHDU hdu = null; 225 for (int i = 0; i < n; i++) { 226 hdu = hdus[i]; 227 hduName = null; 228 // only deal with ImageHDU and TableHDU 229 if (hdu instanceof ImageHDU) { 230 hduName = "ImageHDU #" + nImageHDU++; 231 } 232 else if (hdu instanceof RandomGroupsHDU) { 233 hduName = "RandomGroupsHDU #" + nImageHDU++; 234 } 235 else if (hdu instanceof TableHDU) { 236 if (hdu instanceof AsciiTableHDU) 237 hduName = "AsciiTableHDU #" + nTableHDU++; 238 else if (hdu instanceof BinaryTableHDU) 239 hduName = "BinaryTableHDU #" + nTableHDU++; 240 else 241 hduName = "TableHDU #" + nTableHDU++; 242 } 243 244 if (hduName != null) { 245 oid[0] = hdu.hashCode(); 246 FitsDataset d = new FitsDataset(this, hdu, hduName, oid); 247 rootGroup.addToMemberList(d); 248 } 249 } 250 251 return rootGroup; 252 } 253 254 // Implementing FileFormat 255 @Override 256 public void close() throws IOException 257 { 258 if (fitsFile == null) 259 return; 260 261 DataInput di = fitsFile.getStream(); 262 if (di instanceof InputStream) 263 ((InputStream)di).close(); 264 } 265 266 // Implementing FileFormat 267 @Override 268 public HObject getRootObject() 269 { 270 return rootObject; 271 } 272 273 /** 274 * Get the Fits file. 275 * 276 * @return the Fits file. 277 */ 278 public Fits getFitsFile() { return fitsFile; } 279 280 // implementign FileFormat 281 @Override 282 public Group createGroup(String name, Group pgroup) throws Exception 283 { 284 throw new UnsupportedOperationException("Unsupported createGroup operation for Fits."); 285 } 286 287 // implementign FileFormat 288 @Override 289 public Datatype createDatatype(int tclass, int tsize, int torder, int tsign) throws Exception 290 { 291 throw new UnsupportedOperationException("Unsupported createDatatype operation for Fits."); 292 } 293 294 // implementign FileFormat 295 @Override 296 public Datatype createNamedDatatype(Datatype tnative, String name) throws Exception 297 { 298 throw new UnsupportedOperationException("Fits does not support named datatype."); 299 } 300 301 // implementign FileFormat 302 @Override 303 public Dataset createScalarDS(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, 304 long[] chunks, int gzip, Object fillValue, Object data) throws Exception 305 { 306 throw new UnsupportedOperationException("Unsupported createScalarDS operation."); 307 } 308 309 // implementign FileFormat 310 @Override 311 public Dataset createImage(String name, Group pgroup, Datatype type, long[] dims, long[] maxdims, 312 long[] chunks, int gzip, int ncomp, int intelace, Object data) throws Exception 313 { 314 throw new UnsupportedOperationException("Unsupported createImage operation."); 315 } 316 317 // implementing FileFormat 318 @Override 319 public void delete(HObject obj)throws Exception 320 { 321 throw new UnsupportedOperationException("Unsupported delete operation."); 322 } 323 324 // implementing FileFormat 325 @Override 326 public HObject copy(HObject srcObj, Group dstGroup, String dstName) throws Exception 327 { 328 throw new UnsupportedOperationException("Unsupported copy operation."); 329 } 330 331 /** 332 * copy a dataset into another group. 333 * 334 * @param srcDataset the dataset to be copied. 335 * @param pgroup the group where the dataset is copied to. 336 * 337 * @return the treeNode containing the new copy of the dataset. 338 */ 339 private void copyDataset(Dataset srcDataset, FitsGroup pgroup) throws Exception 340 { 341 throw new UnsupportedOperationException("Unsupported copyDataset operation."); 342 } 343 344 private void copyGroup(FitsGroup srcGroup, FitsGroup pgroup) throws Exception 345 { 346 throw new UnsupportedOperationException("Unsupported copyGroup operation."); 347 } 348 349 /** 350 * Copies the attributes of one object to another object. 351 * 352 * FITS does not support attributes 353 * 354 * @param src 355 * The source object. 356 * @param dst 357 * The destination object. 358 * 359 * @see #copyAttributes(long, long) 360 */ 361 public void copyAttributes(HObject src, HObject dst) 362 { 363 throw new UnsupportedOperationException("Unsupported copyAttributes operation."); 364 } 365 366 /** 367 * Copies the attributes of one object to another object. 368 * 369 * FITS does not support attributes 370 * 371 * @param srcID 372 * The source identifier. 373 * @param dstID 374 * The destination identifier. 375 * 376 * @see #copyAttributes(long, long) 377 */ 378 public void copyAttributes(long srcID, long dstID) 379 { 380 throw new UnsupportedOperationException("Unsupported copyAttributes with id operation."); 381 } 382 383 /** 384 * Creates a new attribute and attached to the object if attribute does 385 * not exist. Otherwise, just update the value of the attribute. 386 * 387 * @param obj 388 * the object which the attribute is to be attached to. 389 * @param attr 390 * the atribute to attach. 391 * @param attrExisted 392 * The indicator if the given attribute exists. 393 */ 394 @Override 395 public void writeAttribute(HObject obj, hdf.object.Attribute attr, boolean attrExisted) throws Exception 396 { 397 throw new UnsupportedOperationException("Unsupported operation."); 398 } 399 400 /** 401 * Returns the version of the library. 402 */ 403 @Override 404 public String getLibversion() 405 { 406 String ver = "Fits Java (version 2.4)"; 407 408 return ver; 409 } 410 411 // implementing FileFormat 412 @Override 413 public HObject get(String path) throws Exception 414 { 415 throw new UnsupportedOperationException("get() is not supported"); 416 } 417}