All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ncsa.hdf.view.DefaultMetaDataView Maven / Gradle / Ivy

The newest version!
/*****************************************************************************
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of the HDF Java Products distribution.                  *
 * The full copyright notice, including terms governing use, modification,   *
 * and redistribution, is contained in the files COPYING and Copyright.html. *
 * COPYING can be found at the root of the source code distribution tree.    *
 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html.         *
 * If you do not have access to either file, you may request a copy from     *
 * [email protected].                                                        *
 ****************************************************************************/

package ncsa.hdf.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.BorderFactory;
import javax.swing.CellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;

import ncsa.hdf.object.Attribute;
import ncsa.hdf.object.CompoundDS;
import ncsa.hdf.object.Dataset;
import ncsa.hdf.object.Datatype;
import ncsa.hdf.object.FileFormat;
import ncsa.hdf.object.Group;
import ncsa.hdf.object.HObject;
import ncsa.hdf.object.ScalarDS;

/**
 * DefaultMetadataView is an dialog window used to show data properties. Data
 * properties include attributes and general information such as object type,
 * data type and data space.
 * 
 * @author Peter X. Cao
 * @version 2.4 9/6/2007
 */
public class DefaultMetaDataView extends JDialog implements ActionListener, MetaDataView {
    private static final long serialVersionUID = 7891048909810508761L;

    /**
     * The main HDFView.
     */
    private ViewManager       viewer;

    /** The HDF data object */
    private HObject           hObject;

    private JTabbedPane       tabbedPane       = null;
    private JTextArea         attrContentArea;
    private JTable            attrTable;  // table to hold a list of attributes
    private DefaultTableModel attrTableModel;
    private JLabel            attrNumberLabel;
    private int               numAttributes;
    private boolean           isH5, isH4;
    private byte[]            userBlock;
    private JTextArea         userBlockArea;
    private JButton           jamButton;

    private JTextField        linkField        = null;

    private FileFormat        fileFormat;
    private String            LinkTObjName;

    private int[]             libver;

    /**
     * Constructs a DefaultMetadataView with the given HDFView.
     */
    public DefaultMetaDataView(ViewManager theView) {
        super((JFrame) theView, false);
        setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);

        setName("DefaultMetaDataView");
        viewer = theView;
        hObject = viewer.getTreeView().getCurrentObject();
        fileFormat = hObject.getFileFormat();
        numAttributes = 0;
        userBlock = null;
        userBlockArea = null;
        libver = new int[2];

        if (hObject == null) {
            dispose();
        }
        else if (hObject.getPath() == null) {
            setTitle("Properties - " + hObject.getName());
        }
        else {
            setTitle("Properties - " + hObject.getPath() + hObject.getName());
        }

        isH5 = hObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
        isH4 = hObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));

        tabbedPane = new JTabbedPane();
        // get the metadata information before add GUI components */
        try {
            hObject.getMetadata();
        }
        catch (Exception ex) {
        }
        tabbedPane.addTab("General", createGeneralPropertyPanel());
        tabbedPane.addTab("Attributes", createAttributePanel());

        boolean isRoot = ((hObject instanceof Group) && ((Group) hObject).isRoot());
        if (isH5 && isRoot) {
            // add panel to display user block
            tabbedPane.addTab("User Block", createUserBlockPanel());
        }
        tabbedPane.setSelectedIndex(0);

        if (isH5) {
            if (hObject.getLinkTargetObjName() != null) {
                LinkTObjName = hObject.getLinkTargetObjName();
            }
        }
        JPanel bPanel = new JPanel();
        bPanel.setName("MetaDataClose");
        JButton b = new JButton("  Close  ");
        b.setName("Close");
        b.setMnemonic(KeyEvent.VK_C);
        b.setActionCommand("Close");
        b.addActionListener(this);
        bPanel.add(b);

        // Add the tabbed pane to this panel.
        JPanel contentPane = (JPanel) getContentPane();
        contentPane.setName("MetaDataContent");
        contentPane.setLayout(new BorderLayout());
        contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        contentPane.setPreferredSize(new Dimension(620, 400));

        contentPane.add("Center", tabbedPane);
        contentPane.add("South", bPanel);

        // locate the H5Property dialog
        Point l = getParent().getLocation();
        l.x += 250;
        l.y += 80;
        setLocation(l);
        pack();
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        String cmd = e.getActionCommand();

        if (cmd.equals("Close")) {
            if (isH5 && linkField != null) checkLinkTargetChanged();

            dispose();
        }
        else if (cmd.equals("Add attribute")) {
            addAttribute(hObject);
        }
        else if (cmd.equals("Delete attribute")) {
            deleteAttribute(hObject);
        }
        else if (cmd.equals("Jam user block")) {
            writeUserBlock();
        }
        else if (cmd.equals("Display user block as")) {
            int type = 0;
            String typeName = (String) ((JComboBox) source).getSelectedItem();
            jamButton.setEnabled(false);
            userBlockArea.setEditable(false);

            if (typeName.equalsIgnoreCase("Text")) {
                type = 0;
                jamButton.setEnabled(true);
                userBlockArea.setEditable(true);
            }
            else if (typeName.equalsIgnoreCase("Binary")) {
                type = 2;
            }
            else if (typeName.equalsIgnoreCase("Octal")) {
                type = 8;
            }
            else if (typeName.equalsIgnoreCase("Hexadecimal")) {
                type = 16;
            }
            else if (typeName.equalsIgnoreCase("Decimal")) {
                type = 10;
            }

            showUserBlockAs(type);
        }
    }

    private final void checkLinkTargetChanged() {
        Group pgroup = null;
        try {
            pgroup = (Group) hObject.getFileFormat().get(hObject.getPath());
        }
        catch (Exception ex) {
        }
        if (pgroup == null) {
            JOptionPane.showMessageDialog(this, "Parent group is null.", getTitle(), JOptionPane.ERROR_MESSAGE);
            return;
        }

        String target_name = linkField.getText();
        if (target_name != null) target_name = target_name.trim();

        int linkType = Group.LINK_TYPE_SOFT;
        if (LinkTObjName.contains(FileFormat.FILE_OBJ_SEP))
            linkType = Group.LINK_TYPE_EXTERNAL;
        else if (target_name.equals("/")) // do not allow to link to the root
            return;

        // no change
        if (target_name.equals(hObject.getLinkTargetObjName())) return;

        // invalid name
        if (target_name == null || target_name.length() < 1) return;

        try {
            fileFormat.createLink(pgroup, hObject.getName(), target_name, linkType);
            hObject.setLinkTargetObjName(target_name);
        }
        catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
        }
    }

    /** returns the data object displayed in this data viewer */
    public HObject getDataObject() {
        return hObject;
    }

    /** Disposes of this dataobserver. */
    public void dispose() {
        super.dispose();
    }

    /** add an attribute to a data object. */
    public Attribute addAttribute(HObject obj) {
        if (obj == null) {
            return null;
        }

        DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj.getFileFormat().getRootNode();
        NewAttributeDialog dialog = new NewAttributeDialog(this, obj, node.breadthFirstEnumeration());
        dialog.setVisible(true);

        Attribute attr = dialog.getAttribute();
        if (attr == null) {
            return null;
        }

        String rowData[] = new String[4]; // name, value, type, size

        rowData[0] = attr.getName();
        rowData[2] = attr.getType().getDatatypeDescription();

        rowData[1] = attr.toString(", ");

        long dims[] = attr.getDataDims();

        rowData[3] = String.valueOf(dims[0]);
        for (int j = 1; j < dims.length; j++) {
            rowData[3] += " x " + dims[j];
        }

        attrTableModel.addRow(rowData);
        attrTableModel.fireTableRowsInserted(attrTableModel.getRowCount() - 1, attrTableModel.getRowCount() - 1);
        numAttributes++;
        attrContentArea.setText("");
        attrNumberLabel.setText("Number of attributes = " + numAttributes);

        return attr;
    }

    /** delete an attribute from a data object. */
    public Attribute deleteAttribute(HObject obj) {
        if (obj == null) {
            return null;
        }

        int idx = attrTable.getSelectedRow();
        if (idx < 0) {
            JOptionPane.showMessageDialog(getOwner(), "No attribute is selected.", getTitle(),
                    JOptionPane.ERROR_MESSAGE);
            return null;
        }

        int option = JOptionPane.showConfirmDialog(this, "Do you want to delete the selected attribute?", getTitle(),
                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);

        if (option == JOptionPane.NO_OPTION) {
            return null;
        }

        List attrList = null;
        try {
            attrList = obj.getMetadata();
        }
        catch (Exception ex) {
            attrList = null;
        }

        if (attrList == null) {
            return null;
        }

        Attribute attr = (Attribute) attrList.get(idx);
        try {
            obj.removeMetadata(attr);
        }
        catch (Exception ex) {
            ;
        }

        attrTableModel.removeRow(idx);
        numAttributes--;
        attrTableModel.fireTableRowsDeleted(idx, idx);

        attrContentArea.setText("");
        attrNumberLabel.setText("Number of attributes = " + numAttributes);

        return attr;
    }

    /**
     * Creates a panel used to dispaly general information of HDF object.
     */
    private JPanel createGeneralPropertyPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout(10, 10));
        panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
        boolean isRoot = ((hObject instanceof Group) && ((Group) hObject).isRoot());
        FileFormat theFile = hObject.getFileFormat();

        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());

        JPanel lp = new JPanel();
        lp.setLayout(new GridLayout(5, 1));

        if (isRoot) {
            lp.add(new JLabel("File Name: "));
            lp.add(new JLabel("File Path: "));
            lp.add(new JLabel("File Type: "));
            if (isH5) {
                try {
                    libver = hObject.getFileFormat().getLibBounds();
                }
                catch (Exception ex) {
                    ex.printStackTrace();
                }
                if (((libver[0] == 0) || (libver[0] == 1)) && (libver[1] == 1))
                    lp.add(new JLabel("Library version: "));
            }
        }
        else {
            lp.add(new JLabel("Name: "));
            if (isH5) {
                if (hObject.getLinkTargetObjName() != null) lp.add(new JLabel("Link To Target: "));
            }
            lp.add(new JLabel("Path: "));
            lp.add(new JLabel("Type: "));

            /* bug #926 to remove the OID, put it back on Nov. 20, 2008, --PC */
            if (isH4) {
                lp.add(new JLabel("Tag, Ref:        "));
            }
            else {
                lp.add(new JLabel("Object Ref:       "));
            }
        }

        JPanel rp = new JPanel();
        rp.setLayout(new GridLayout(5, 1));

        JLabel nameField = new JLabel(hObject.getName());
        rp.add(nameField);

        JPanel targetObjPanel = new JPanel();
        JButton ChangeTargetObjButton = new JButton("Change");
        ChangeTargetObjButton.setActionCommand("Change link target");
        ChangeTargetObjButton.addActionListener(this);

        if (isH5) {
            if (hObject.getLinkTargetObjName() != null) {
                linkField = new JTextField(hObject.getLinkTargetObjName());
                targetObjPanel.setLayout(new BorderLayout());
                targetObjPanel.add(linkField, BorderLayout.CENTER);
                // targetObjPanel.add(ChangeTargetObjButton, BorderLayout.EAST);
                rp.add(targetObjPanel);
            }
        }

        JLabel pathField = new JLabel();
        if (isRoot) {
            pathField.setText((new File(hObject.getFile())).getParent());
        }
        else {
            pathField.setText(hObject.getPath());
        }
        rp.add(pathField);

        String typeStr = "Unknown";
        String fileInfo = "";
        if (isRoot) {
            long size = 0;
            try {
                size = (new File(hObject.getFile())).length();
            }
            catch (Exception ex) {
                size = -1;
            }
            size /= 1024;

            int groupCount = 0, datasetCount = 0;
            DefaultMutableTreeNode root = (DefaultMutableTreeNode) theFile.getRootNode();
            DefaultMutableTreeNode theNode = null;
            Enumeration local_enum = root.depthFirstEnumeration();
            while (local_enum.hasMoreElements()) {
                theNode = (DefaultMutableTreeNode) local_enum.nextElement();
                if (theNode.getUserObject() instanceof Group) {
                    groupCount++;
                }
                else {
                    datasetCount++;
                }
            }
            fileInfo = "size=" + size + "K,  groups=" + groupCount + ",  datasets=" + datasetCount;
        }

        if (isRoot) {
            if (isH5) {
                typeStr = "HDF5,  " + fileInfo;
            }
            else if (isH4) {
                typeStr = "HDF4,  " + fileInfo;
            }
            else {
                typeStr = fileInfo;
            }
        }
        else if (isH5) {
            if (hObject instanceof Group) {
                typeStr = "HDF5 Group";
            }
            else if (hObject instanceof ScalarDS) {
                typeStr = "HDF5 Scalar Dataset";
            }
            else if (hObject instanceof CompoundDS) {
                typeStr = "HDF5 Compound Dataset";
            }
            else if (hObject instanceof Datatype) {
                typeStr = "HDF5 Named Datatype";
            }
        }
        else if (isH4) {
            if (hObject instanceof Group) {
                typeStr = "HDF4 Group";
            }
            else if (hObject instanceof ScalarDS) {
                ScalarDS ds = (ScalarDS) hObject;
                if (ds.isImage()) {
                    typeStr = "HDF4 Raster Image";
                }
                else {
                    typeStr = "HDF4 SDS";
                }
            }
            else if (hObject instanceof CompoundDS) {
                typeStr = "HDF4 Vdata";
            }
        }
        else {
            if (hObject instanceof Group) {
                typeStr = "Group";
            }
            else if (hObject instanceof ScalarDS) {
                typeStr = "Scalar Dataset";
            }
            else if (hObject instanceof CompoundDS) {
                typeStr = "Compound Dataset";
            }
        }

        JLabel typeField = new JLabel(typeStr);
        rp.add(typeField);

        if (isRoot && isH5) {
            String libversion = null;
            if ((libver[0] == 0) && (libver[1] == 1))
                libversion = "Earliest and Latest";
            else if ((libver[0] == 1) && (libver[1] == 1)) libversion = "Latest and Latest";
            JLabel libverbound = new JLabel(libversion);
            rp.add(libverbound);
        }

        /* bug #926 to remove the OID, put it back on Nov. 20, 2008, --PC */
        String oidStr = null;
        long[] OID = hObject.getOID();
        if (OID != null) {
            oidStr = String.valueOf(OID[0]);
            for (int i = 1; i < OID.length; i++) {
                oidStr += ", " + OID[i];
            }
        }

        if (!isRoot) {
            JLabel oidField = new JLabel(oidStr);
            rp.add(oidField);
        }

        JPanel tmpP = new JPanel();
        tmpP.setLayout(new BorderLayout());
        tmpP.add("West", lp);
        tmpP.add("Center", rp);
        tmpP.setBorder(new TitledBorder(""));

        topPanel.add("North", new JLabel(""));
        topPanel.add("Center", tmpP);

        JPanel infoPanel = null;
        if (hObject instanceof Group) {
            infoPanel = createGroupInfoPanel((Group) hObject);
        }
        else if (hObject instanceof Dataset) {
            infoPanel = createDatasetInfoPanel((Dataset) hObject);
        }
        else if (hObject instanceof Datatype) {
            infoPanel = createNamedDatatypeInfoPanel((Datatype) hObject);
        }

        panel.add(topPanel, BorderLayout.NORTH);
        if (infoPanel != null) {
            panel.add(infoPanel, BorderLayout.CENTER);
        }

        return panel;
    }

    /**
     * Creates a panel used to display HDF group information.
     */
    private JPanel createGroupInfoPanel(Group g) {
        JPanel panel = new JPanel();

        List mlist = g.getMemberList();
        if (mlist == null) {
            return panel;
        }

        int n = mlist.size();
        if (n <= 0) {
            return panel;
        }

        String rowData[][] = new String[n][2];
        for (int i = 0; i < n; i++) {
            HObject theObj = (HObject) mlist.get(i);
            rowData[i][0] = theObj.getName();
            if (theObj instanceof Group) {
                rowData[i][1] = "Group";
            }
            else if (theObj instanceof Dataset) {
                rowData[i][1] = "Dataset";
            }
        }

        String[] columnNames = { "Name", "Type" };
        JTable table = new JTable(rowData, columnNames) {
            private static final long serialVersionUID = -834321929059590629L;

            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        table.setName("GroupInfo");
        table.setCellSelectionEnabled(false);

        // set cell height for large fonts
        int cellRowHeight = Math.max(16, table.getFontMetrics(table.getFont()).getHeight());
        table.setRowHeight(cellRowHeight);

        table.getTableHeader().setReorderingAllowed(false);
        JScrollPane scroller = new JScrollPane(table);

        panel.setLayout(new BorderLayout());
        if (g.getNumberOfMembersInFile() < ViewProperties.getMaxMembers()) {
            panel.add(new JLabel("Number of members: " + n), BorderLayout.NORTH);
        }
        else {
            panel.add(new JLabel("Number of members: " + n + " (in memory), " + g.getNumberOfMembersInFile()
                    + " (in file)"), BorderLayout.NORTH);
        }
        panel.add(scroller, BorderLayout.CENTER);
        panel.setBorder(new TitledBorder("Group Members"));

        return panel;
    }

    private JPanel createNamedDatatypeInfoPanel(Datatype t) {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        JTextArea infoArea = new JTextArea(t.getDatatypeDescription());
        infoArea.setEditable(false);

        panel.add(infoArea, BorderLayout.CENTER);

        return panel;
    }

    /**
     * Creates a panel used to display HDF dataset information.
     */
    private JPanel createDatasetInfoPanel(Dataset d) {
        JPanel lp = new JPanel();
        lp.setLayout(new GridLayout(4, 1));
        lp.add(new JLabel("No. of Dimension(s): "));
        lp.add(new JLabel("Dimension Size(s): "));
        lp.add(new JLabel("Max Dimension Size(s): "));
        lp.add(new JLabel("Data Type: "));

        JPanel rp = new JPanel();
        rp.setLayout(new GridLayout(4, 1));

        if (d.getRank() <= 0) {
            d.init();
        }
        JTextField txtf = new JTextField("" + d.getRank());
        txtf.setEditable(false);
        rp.add(txtf);

        String dimStr = null;
        String maxDimStr = null;
        long dims[] = d.getDims();
        long maxDims[] = d.getMaxDims();
        if (dims != null) {
            String[] dimNames = d.getDimNames();
            boolean hasDimNames = ((dimNames != null) && (dimNames.length == dims.length));
            StringBuffer sb = new StringBuffer();
            StringBuffer sb2 = new StringBuffer();

            sb.append(dims[0]);
            if (hasDimNames) {
                sb.append(" (");
                sb.append(dimNames[0]);
                sb.append(")");
            }

            if (maxDims[0] < 0)
                sb2.append("Unlimited");
            else
                sb2.append(maxDims[0]);

            for (int i = 1; i < dims.length; i++) {
                sb.append(" x ");
                sb.append(dims[i]);
                if (hasDimNames) {
                    sb.append(" (");
                    sb.append(dimNames[i]);
                    sb.append(")");
                }

                sb2.append(" x ");
                if (maxDims[i] < 0)
                    sb2.append("Unlimited");
                else
                    sb2.append(maxDims[i]);

            }
            dimStr = sb.toString();
            maxDimStr = sb2.toString();
        }
        txtf = new JTextField(dimStr);
        txtf.setEditable(false);
        rp.add(txtf);

        txtf = new JTextField(maxDimStr);
        txtf.setEditable(false);
        rp.add(txtf);

        String typeStr = null;
        if (d instanceof ScalarDS) {
            ScalarDS sd = (ScalarDS) d;
            typeStr = sd.getDatatype().getDatatypeDescription();
        }
        else if (d instanceof CompoundDS) {
            if (isH4) {
                typeStr = "Vdata";
            }
            else {
                typeStr = "Compound";
            }
        }

        txtf = new JTextField(typeStr);
        txtf.setEditable(false);
        rp.add(txtf);

        JPanel infoP = new JPanel();
        infoP.setLayout(new BorderLayout());
        infoP.add(lp, BorderLayout.WEST);
        infoP.add(rp, BorderLayout.CENTER);
        infoP.setBorder(new TitledBorder(""));

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(infoP, BorderLayout.NORTH);
        panel.setBorder(new TitledBorder("Dataspace and Datatype"));

        // add compound datatype information
        if (d instanceof CompoundDS) {
            CompoundDS compound = (CompoundDS) d;

            int n = compound.getMemberCount();
            if (n > 0) {
                String rowData[][] = new String[n][3];
                String names[] = compound.getMemberNames();
                Datatype types[] = compound.getMemberTypes();
                int orders[] = compound.getMemberOrders();

                for (int i = 0; i < n; i++) {
                    rowData[i][0] = names[i];
                    int mDims[] = compound.getMemeberDims(i);
                    if (mDims == null) {
                        rowData[i][2] = String.valueOf(orders[i]);

                        if (isH4 && types[i].getDatatypeClass() == Datatype.CLASS_STRING) {
                            rowData[i][2] = String.valueOf(types[i].getDatatypeSize());
                        }
                    }
                    else {
                        String mStr = String.valueOf(mDims[0]);
                        int m = mDims.length;
                        for (int j = 1; j < m; j++) {
                            mStr += " x " + mDims[j];
                        }
                        rowData[i][2] = mStr;
                    }
                    rowData[i][1] = types[i].getDatatypeDescription();
                }

                String[] columnNames = { "Name", "Type", "Array Size" };
                JTable table = new JTable(rowData, columnNames) {
                    private static final long serialVersionUID = -1517773307922536859L;

                    public boolean isCellEditable(int row, int column) {
                        return false;
                    }
                };
                table.setName("CompoundMetaData");
                table.setCellSelectionEnabled(false);
                table.getTableHeader().setReorderingAllowed(false);
                panel.add(new JScrollPane(table), BorderLayout.CENTER);

                // set cell height for large fonts
                int cellRowHeight = Math.max(16, table.getFontMetrics(table.getFont()).getHeight());
                table.setRowHeight(cellRowHeight);
            } // if (n > 0)
        } // if (d instanceof Compound)

        // add compression and data lauoyt information
        // try { d.getMetadata(); } catch (Exception ex) {}
        String chunkInfo = "";
        long[] chunks = d.getChunkSize();
        if (chunks == null) {
            chunkInfo = "NONE";
        }
        else {
            int n = chunks.length;
            chunkInfo = String.valueOf(chunks[0]);
            for (int i = 1; i < n; i++) {
                chunkInfo += " X " + chunks[i];
            }
        }

        JPanel bPanel = new JPanel();
        bPanel.setBorder(new TitledBorder(""));
        bPanel.setLayout(new BorderLayout());
        lp = new JPanel();
        lp.setLayout(new GridLayout(3, 1));
        lp.add(new JLabel("Chunking: "));
        lp.add(new JLabel("Compression: "));
        lp.add(new JLabel("Fill value: "));
        bPanel.add(lp, BorderLayout.WEST);

        Object fillValue = null;
        String fillValueInfo = "NONE";
        if (d instanceof ScalarDS) fillValue = ((ScalarDS) d).getFillValue();
        if (fillValue != null) {
            if (fillValue.getClass().isArray()) {
                int len = Array.getLength(fillValue);
                fillValueInfo = Array.get(fillValue, 0).toString();
                for (int i = 1; i < len; i++) {
                    fillValueInfo += ", ";
                    fillValueInfo += Array.get(fillValue, i).toString();
                }
            }
            else
                fillValueInfo = fillValue.toString();
        }

        rp = new JPanel();
        rp.setLayout(new GridLayout(3, 1));
        rp.add(new JLabel(chunkInfo));
        rp.add(new JLabel(d.getCompression()));
        rp.add(new JLabel(fillValueInfo));
        bPanel.add(rp, BorderLayout.CENTER);

        panel.add(bPanel, BorderLayout.SOUTH);

        return panel;
    }

    /**
     * Creates a panel used to display attribute information.
     */
    private JPanel createAttributePanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        // panel.setBorder(BorderFactory.createEmptyBorder(10,0,0,0));

        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());
        attrNumberLabel = new JLabel("Number of attributes = 0");
        topPanel.add(attrNumberLabel, BorderLayout.WEST);

        FileFormat theFile = hObject.getFileFormat();
        JPanel bPanel = new JPanel();
        JButton b = new JButton(" Add ");
        b.setMnemonic('A');
        b.addActionListener(this);
        b.setActionCommand("Add attribute");
        bPanel.add(b);
        b.setEnabled(!theFile.isReadOnly());

        if (isH5) {
            // deleting is not supported by HDF4
            b = new JButton("Delete");
            b.setMnemonic('D');
            b.addActionListener(this);
            b.setActionCommand("Delete attribute");
            bPanel.add(b);
            b.setEnabled(!theFile.isReadOnly());
        }
        topPanel.add(bPanel, BorderLayout.EAST);

        panel.add(topPanel, BorderLayout.NORTH);

        List attrList = null;

        try {
            attrList = hObject.getMetadata();
        }
        catch (Exception ex) {
            attrList = null;
        }
        if (attrList != null) {
            numAttributes = attrList.size();
        }

        String[] columnNames = { "Name", "Value", "Type", "Array Size" };
        attrTableModel = new DefaultTableModel(columnNames, numAttributes);

        attrTable = new JTable(attrTableModel) {
            private static final long serialVersionUID = 2590244645972259454L;
            int                       lastSelectedRow  = -1;
            int                       lastSelectedCol  = -1;

            public boolean isCellEditable(int row, int column) {
                return ((column == 1) || (isH5 && (column == 0))); // only
                // attribute
                // value and
                // name can
                // be changed
            }

            public void editingStopped(ChangeEvent e) {
                int row = getEditingRow();
                int col = getEditingColumn();
                String oldValue = (String) getValueAt(row, col);

                super.editingStopped(e);

                Object source = e.getSource();

                if (source instanceof CellEditor) {
                    CellEditor editor = (CellEditor) source;
                    String newValue = (String) editor.getCellEditorValue();
                    setValueAt(oldValue, row, col); // set back to what it is
                    updateAttributeValue(newValue, row, col);
                }
            }

            public boolean isCellSelected(int row, int col) {

                if ((getSelectedRow() == row) && (getSelectedColumn() == col)
                        && !((lastSelectedRow == row) && (lastSelectedCol == col))) {
                    // selection is changed
                    Object attrV = getValueAt(row, col);
                    if (attrV != null) {
                        attrContentArea.setText(attrV.toString());
                    }
                    lastSelectedRow = row;
                    lastSelectedCol = col;
                }

                return super.isCellSelected(row, col);
            }
        };

        attrTable.setName("attributes");
        attrTable.setRowSelectionAllowed(false);
        attrTable.setCellSelectionEnabled(true);
        attrTable.getTableHeader().setReorderingAllowed(false);
        attrTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        // set cell height for large fonts
        int cellRowHeight = Math.max(16, attrTable.getFontMetrics(attrTable.getFont()).getHeight());
        attrTable.setRowHeight(cellRowHeight);

        JScrollPane scroller1 = new JScrollPane(attrTable);
        attrContentArea = new JTextArea();
        attrContentArea.setLineWrap(true);
        attrContentArea.setEditable(false);
        Insets m = new Insets(5, 5, 5, 5);
        attrContentArea.setMargin(m);

        JScrollPane scroller2 = new JScrollPane(attrContentArea);
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scroller1, scroller2);

        // set the divider location
        int h = Math.min((numAttributes + 2) * attrTable.getRowHeight(), scroller1.getPreferredSize().height - 40);
        splitPane.setDividerLocation(h);
        panel.add(splitPane, BorderLayout.CENTER);

        if (attrList == null) {
            return panel;
        }

        Attribute attr = null;
        String name, type, size;
        attrNumberLabel.setText("Number of attributes = " + numAttributes);
        for (int i = 0; i < numAttributes; i++) {
            attr = (Attribute) attrList.get(i);
            name = attr.getName();

            // boolean isUnsigned = false;
            type = attr.getType().getDatatypeDescription();
            // isUnsigned = attr.getType().isUnsigned();

            if (attr.isScalar()) {
                size = "Scalar";
            }
            else {
                long dims[] = attr.getDataDims();
                size = String.valueOf(dims[0]);
                for (int j = 1; j < dims.length; j++) {
                    size += " x " + dims[j];
                }
            }

            attrTable.setValueAt(name, i, 0);
            attrTable.setValueAt(attr.toString(", "), i, 1);
            attrTable.setValueAt(type, i, 2);
            attrTable.setValueAt(size, i, 3);
        } // for (int i=0; i attrList = null;
        try {
            attrList = hObject.getMetadata();
        }
        catch (Exception ex) {
            JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
            return;
        }

        Attribute attr = (Attribute) attrList.get(row);

        if (col == 1) { // To change attribute value
            Object data = attr.getValue();
            if (data == null) {
                return;
            }

            int array_length = Array.getLength(data);
            StringTokenizer st = new StringTokenizer(newValue, ",");
            if (st.countTokens() < array_length) {
                JOptionPane.showMessageDialog(getOwner(), "More data value needed: " + newValue, getTitle(),
                        JOptionPane.ERROR_MESSAGE);
                return;
            }

            char NT = ' ';
            String cName = data.getClass().getName();
            int cIndex = cName.lastIndexOf("[");
            if (cIndex >= 0) {
                NT = cName.charAt(cIndex + 1);
            }
            boolean isUnsigned = attr.isUnsigned();

            double d = 0;
            String theToken = null;
            long max = 0, min = 0;
            for (int i = 0; i < array_length; i++) {
                max = min = 0;
                theToken = st.nextToken().trim();
                try {
                    if (!(Array.get(data, i) instanceof String)) {
                        d = Double.parseDouble(theToken);
                    }
                }
                catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
                    return;
                }

                if (isUnsigned && (d < 0)) {
                    JOptionPane.showMessageDialog(getOwner(), "Negative value for unsigned integer: " + theToken,
                            getTitle(), JOptionPane.ERROR_MESSAGE);
                    return;
                }

                switch (NT) {
                    case 'B': {
                        if (isUnsigned) {
                            min = 0;
                            max = 255;
                        }
                        else {
                            min = Byte.MIN_VALUE;
                            max = Byte.MAX_VALUE;
                        }

                        if ((d > max) || (d < min)) {
                            JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max
                                    + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE);
                        }
                        else {
                            Array.setByte(data, i, (byte) d);
                        }
                        break;
                    }
                    case 'S': {
                        if (isUnsigned) {
                            min = 0;
                            max = 65535;
                        }
                        else {
                            min = Short.MIN_VALUE;
                            max = Short.MAX_VALUE;
                        }

                        if ((d > max) || (d < min)) {
                            JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max
                                    + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE);
                        }
                        else {
                            Array.setShort(data, i, (short) d);
                        }
                        break;
                    }
                    case 'I': {
                        if (isUnsigned) {
                            min = 0;
                            max = 4294967295L;
                        }
                        else {
                            min = Integer.MIN_VALUE;
                            max = Integer.MAX_VALUE;
                        }

                        if ((d > max) || (d < min)) {
                            JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max
                                    + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE);
                        }
                        else {
                            Array.setInt(data, i, (int) d);
                        }
                        break;
                    }
                    case 'J':
                        if (isUnsigned) {
                            if (theToken != null) {
                                String theValue = theToken;
                                BigInteger Jmax = new BigInteger("18446744073709551615");
                                BigInteger big = new BigInteger(theValue); 
                                if ((big.compareTo(Jmax)>0) || (big.compareTo(BigInteger.ZERO)<0)) {
                                    JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max
                                            + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE);
                                }
                                Array.setLong(data, i, big.longValue());
                            }
                            else
                                Array.set(data, i, (Object)theToken);
                        }
                        else {
                            min = Long.MIN_VALUE;
                            max = Long.MAX_VALUE;
                            if ((d > max) || (d < min)) {
                                JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max
                                        + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE);
                            }
                
                            Array.setLong(data, i, (long) d);
                        }
                        break;
                    case 'F':
                        Array.setFloat(data, i, (float) d);
                        break;
                    case 'D':
                        Array.setDouble(data, i, d);
                        break;
                    default:
                        Array.set(data, i, (Object)theToken);
                        break;
                }
            }

            try {
                hObject.getFileFormat().writeAttribute(hObject, attr, true);
            }
            catch (Exception ex) {
                JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
                return;
            }

            // update the attribute table
            attrTable.setValueAt(attr.toString(", "), row, 1);
        }

        if ((col == 0) && isH5) { // To change attribute name
            try {
                hObject.getFileFormat().renameAttribute(hObject, attrName, newValue);
            }
            catch (Exception ex) {
                JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
                return;
            }

            // update the attribute table
            attrTable.setValueAt(newValue, row, 0);
        }
    }

    private void writeUserBlock() {
        if (!isH5) {
            return;
        }

        int blkSize0 = 0;
        if (userBlock != null) {
            blkSize0 = userBlock.length;
            // The super block space is allocated by offset 0, 512, 1024, 2048,
            // etc
            if (blkSize0 > 0) {
                int offset = 512;
                while (offset < blkSize0) {
                    offset *= 2;
                }
                blkSize0 = offset;
            }
        }

        int blkSize1 = 0;
        String userBlockStr = userBlockArea.getText();
        if (userBlockStr == null) {
            if (blkSize0 <= 0) {
                return; // nothing to write
            }
            else {
                userBlockStr = " "; // want to wipe out old userblock content
            }
        }
        byte buf[] = null;
        buf = userBlockStr.getBytes();

        blkSize1 = buf.length;
        if (blkSize1 <= blkSize0) {
            java.io.RandomAccessFile raf = null;
            try {
                raf = new java.io.RandomAccessFile(hObject.getFile(), "rw");
            }
            catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Can't open output file: " + hObject.getFile(), getTitle(),
                        JOptionPane.ERROR_MESSAGE);
                return;
            }

            try {
                raf.seek(0);
                raf.write(buf, 0, buf.length);
                raf.seek(buf.length);
                if (blkSize0 > buf.length) {
                    byte[] padBuf = new byte[blkSize0 - buf.length];
                    raf.write(padBuf, 0, padBuf.length);
                }
            }
            catch (Exception ex) {
            }
            try {
                raf.close();
            }
            catch (Exception ex) {
            }

            JOptionPane.showMessageDialog(this, "Saving user block is successful.", getTitle(),
                    JOptionPane.INFORMATION_MESSAGE);
        }
        else {
            // must rewrite the whole file
            // must rewrite the whole file
            int op = JOptionPane.showConfirmDialog(this,
                    "The user block to write is " + blkSize1 + " (bytes),\n"
                            + "which is larger than the user block space in file " + blkSize0 + " (bytes).\n"
                            + "To expand the user block, the file must be rewriten.\n\n"
                            + "Do you want to replace the current file? Click "
                            + "\n\"Yes\" to replace the current file," + "\n\"No\" to save to a different file, "
                            + "\n\"Cancel\" to quit without saving the change.\n\n ", getTitle(),
                            JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);

            if (op == JOptionPane.CANCEL_OPTION) {
                return;
            }

            String fin = hObject.getFile();

            String fout = fin + "~copy.h5";
            if (fin.endsWith(".h5")) {
                fout = fin.substring(0, fin.length() - 3) + "~copy.h5";
            }
            else if (fin.endsWith(".hdf5")) {
                fout = fin.substring(0, fin.length() - 5) + "~copy.h5";
            }

            File outFile = null;

            if (op == JOptionPane.NO_OPTION) {
                JFileChooser fchooser = new JFileChooser();
                fchooser.setFileFilter(DefaultFileFilter.getFileFilterHDF5());
                fchooser.setSelectedFile(new File(fout));

                int returnVal = fchooser.showSaveDialog(this);
                if (returnVal != JFileChooser.APPROVE_OPTION) {
                    return;
                }

                File choosedFile = fchooser.getSelectedFile();
                if (choosedFile == null) {
                    return;
                }

                outFile = choosedFile;
                fout = outFile.getAbsolutePath();
            }
            else {
                outFile = new File(fout);
            }

            if (!outFile.exists()) {
                try {
                    outFile.createNewFile();
                }
                catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, "Fail to write user block into file. ", getTitle(),
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }
            }

            // close the file
            ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Close file");
            ((HDFView) viewer).actionPerformed(e);

            if (DefaultFileFilter.setHDF5UserBlock(fin, fout, buf)) {
                if (op == JOptionPane.NO_OPTION) {
                    fin = fout; // open the new file
                }
                else {
                    File oldFile = new File(fin);
                    boolean status = oldFile.delete();
                    if (status) {
                        outFile.renameTo(oldFile);
                    }
                    else {
                        JOptionPane.showMessageDialog(this,
                                "Cannot replace the current file.\nPlease save to a different file.", getTitle(),
                                JOptionPane.ERROR_MESSAGE);
                        outFile.delete();
                    }
                }
            }
            else {
                JOptionPane.showMessageDialog(this, "Fail to write user block into file. ", getTitle(),
                        JOptionPane.ERROR_MESSAGE);
                outFile.delete();
            }

            // reopen the file
            dispose();
            e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Open file://" + fin);
            ((HDFView) viewer).actionPerformed(e);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy