001 /* @(#)FitsHDUnit.java $Revision: 1.7 $ $Date: 2002/02/28 09:20:28 $ 002 * 003 * Copyright (C) 202 European Southern Observatory 004 * License: GNU General Public License version 2 or later 005 */ 006 package org.eso.fits; 007 008 import java.lang.*; 009 import java.util.*; 010 import java.io.*; 011 012 /** FitsHDUnit class represents a FITS header plus a FITS data unit 013 * 014 * @version $Revision: 1.7 $ $Date: 2002/02/28 09:20:28 $ 015 * @author P.Grosbol, DMD/ESO, <pgrosbol@eso.org> 016 */ 017 public class FitsHDUnit { 018 019 private FitsHeader header; 020 private FitsData data; 021 // changeHeader flag set by FitsMatrix, FitsTable or FitsRGroup constructors to indicate more headers after data 022 private boolean changeHeader = false; 023 private long headerOffset = 0; 024 private RandomAccessFile headerFile = null; 025 026 /** Constructor for FitsHDUnit class given a FITS stream and a internal 027 * storage flag. 028 * 029 * @param file DataInput file positioned at the start of the 030 * header/data unit 031 * @param sflag Flag for storing data matrix internally 032 * @exception FitsException */ 033 public FitsHDUnit(DataInput file, boolean sflag) throws FitsException { 034 if (file instanceof RandomAccessFile) { 035 headerFile = (RandomAccessFile) file; 036 try { 037 headerOffset = headerFile.getFilePointer(); 038 } catch (IOException e) { 039 throw new FitsException("Cannot read header offset",FitsException.FILE); 040 } 041 } 042 043 header = new FitsHeader(file); 044 int type = header.getType(); 045 switch (type) { 046 case Fits.IMAGE: 047 data = new FitsMatrix(header, file, sflag); 048 break; 049 case Fits.BTABLE: 050 case Fits.ATABLE: 051 data = new FitsTable(header, file, sflag); 052 break; 053 case Fits.RGROUP: 054 data = new FitsRGroup(header, file, sflag); 055 break; 056 } 057 changeHeader = false; 058 } 059 060 /** Constructor from individual header and data objects. 061 * 062 * @param header new FitsHeader object to used 063 * @param data new FitsData object associated to header 064 * @exception FitsException */ 065 public FitsHDUnit(FitsHeader header, FitsData data) throws FitsException { 066 this.header = header; 067 this.data = data; 068 changeHeader = true; 069 } 070 071 /** Get the type of Header/Data unit as indicated by its header. */ 072 public int getType(){ 073 return header.getType(); 074 } 075 076 /** Check if HD unit can be save to FITS file in place that is 077 * a FITS file exists and has space enough. 078 */ 079 public boolean canSave() { 080 if (changeHeader || (headerFile==null)) { 081 return false; 082 } 083 084 int nfill = header.getHeaderSpace() - header.getNoKeywords() - 1; 085 if (nfill<0) { 086 return false; 087 } 088 return true; 089 } 090 091 /** Save changes of a HD unit to FITS file. The HDunit must have 092 * been created from a read/write RandomAccess disk file. 093 * There are no check for the consistence of Header and Data. 094 * 095 * @exception IOException, FitsException */ 096 protected void saveFile(RandomAccessFile file) 097 throws IOException, FitsException { 098 if (changeHeader) { 099 throw new FitsException("HD unit modified", FitsException.FILE); 100 } 101 if (headerFile == null) { 102 throw new FitsException("No header file", FitsException.FILE); 103 } 104 105 int nfill = header.getHeaderSpace() - header.getNoKeywords() - 1; 106 107 if (nfill<0) { 108 throw new FitsException("No space in FITS header",FitsException.NOHEADERSPACE); 109 } 110 111 file.seek(headerOffset); 112 file.write((header.toString()).getBytes()); // Write the header 113 while (0<nfill--) file.write(Fits.BLANK_CARD.getBytes()); 114 file.write(Fits.END_CARD.getBytes()); 115 } 116 117 /** Write FITS header/Data unit to a DataOutput stream. 118 * 119 * @param file DataOutput object to which to write 120 * @exception IOException, FitsException */ 121 public void writeFile(DataOutput file) throws IOException, FitsException { 122 int nokw = header.getNoKeywords(); 123 if (nokw<2) { 124 throw new FitsException("Bad FITS header",FitsException.HEADER); 125 } 126 127 file.write((header.toString()).getBytes()); // Write the header 128 129 // Add BLANK-cards and the final END-card to fill the FITS record 130 131 int nfill = Fits.NOCARDS*(nokw/Fits.NOCARDS + 1) - nokw - 1; 132 while (0<nfill--) file.write(Fits.BLANK_CARD.getBytes()); 133 file.write(Fits.END_CARD.getBytes()); 134 135 data.writeFile(file); 136 } 137 138 /** Remove all references to the DataInput file from data unit */ 139 public void closeFile() { 140 headerFile = null; 141 data.closeFile(); 142 } 143 144 /** Return the FitsData object in the Header/Data unit */ 145 public FitsData getData(){ 146 return data; 147 } 148 149 /** Return the header object in the Header/Data unit */ 150 public FitsHeader getHeader(){ 151 return header; 152 } 153 }