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