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 }