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 files COPYING and Copyright.html. *
009 * COPYING can be found at the root of the source code distribution tree.    *
010 * Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html.         *
011 * If you do not have access to either file, you may request a copy from     *
012 * help@hdfgroup.org.                                                        *
013 ****************************************************************************/
014
015package hdf.view;
016
017import java.awt.BorderLayout;
018import java.awt.Color;
019import java.awt.Component;
020import java.awt.Cursor;
021import java.awt.GridLayout;
022import java.awt.Point;
023import java.awt.Toolkit;
024import java.awt.event.ActionEvent;
025import java.awt.event.ActionListener;
026import java.awt.event.KeyAdapter;
027import java.awt.event.KeyEvent;
028import java.awt.event.MouseAdapter;
029import java.awt.event.MouseEvent;
030import java.io.BufferedInputStream;
031import java.io.BufferedOutputStream;
032import java.io.File;
033import java.io.FileInputStream;
034import java.io.FileOutputStream;
035import java.io.Serializable;
036import java.lang.reflect.Constructor;
037import java.lang.reflect.Method;
038import java.util.BitSet;
039import java.util.Enumeration;
040import java.util.HashMap;
041import java.util.Iterator;
042import java.util.List;
043import java.util.Vector;
044
045import javax.swing.BorderFactory;
046import javax.swing.ButtonGroup;
047import javax.swing.Icon;
048import javax.swing.JButton;
049import javax.swing.JComboBox;
050import javax.swing.JComponent;
051import javax.swing.JDialog;
052import javax.swing.JFileChooser;
053import javax.swing.JFrame;
054import javax.swing.JInternalFrame;
055import javax.swing.JMenu;
056import javax.swing.JMenuItem;
057import javax.swing.JOptionPane;
058import javax.swing.JPanel;
059import javax.swing.JPopupMenu;
060import javax.swing.JRadioButton;
061import javax.swing.JSeparator;
062import javax.swing.JTree;
063import javax.swing.border.BevelBorder;
064import javax.swing.border.SoftBevelBorder;
065import javax.swing.border.TitledBorder;
066import javax.swing.tree.DefaultMutableTreeNode;
067import javax.swing.tree.DefaultTreeCellRenderer;
068import javax.swing.tree.DefaultTreeModel;
069import javax.swing.tree.MutableTreeNode;
070import javax.swing.tree.TreeNode;
071import javax.swing.tree.TreePath;
072
073import hdf.object.CompoundDS;
074import hdf.object.Dataset;
075import hdf.object.Datatype;
076import hdf.object.FileFormat;
077import hdf.object.Group;
078import hdf.object.HObject;
079import hdf.object.ScalarDS;
080import hdf.view.ViewProperties.DATA_VIEW_KEY;
081
082/**
083 * 
084 * <p>
085 * TreeView defines APIs for open a file and display the file structure in tree
086 * structure.
087 * </p>
088 * 
089 * <p>
090 * TreeView uses folders and leaf nodes to represent groups and data objects in
091 * the file. You can expand or collapse folders to navigate data objects in the
092 * file.
093 * </p>
094 * 
095 * <p>
096 * From the TreeView, you can open data content or metadata of selected object.
097 * You can selet object(s) to delete or add new object to the file.
098 * </p>
099 * 
100 * @author Peter X. Cao
101 * @version 2.4 9/6/2007
102 */
103public class DefaultTreeView extends JPanel implements TreeView, ActionListener {
104    private static final long            serialVersionUID    = 4092566164712521186L;
105
106    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultTreeView.class);
107
108    /** the owner of this treeview */
109    private ViewManager                  viewer;
110
111    /**
112     * The super root of tree: all open files start at this root.
113     */
114    private final DefaultMutableTreeNode root;
115
116    /**
117     * The tree which holds file structures.
118     */
119    private final JTree                  tree;
120
121    /**
122     * The tree model
123     */
124    private final DefaultTreeModel       treeModel;
125
126    /** A list open files. */
127    private final List<FileFormat>       fileList;
128
129    private final Toolkit                toolkit;
130
131    /** Selected file */
132    private FileFormat                   selectedFile;
133
134    /** The current selected node. */
135    private DefaultMutableTreeNode       selectedNode;
136
137    /** The current selected TreePath. */
138    private TreePath                     selectedTreePath;
139
140    /** the current selected object */
141    private HObject                      selectedObject;
142
143    /** flag to indicate if the dataset is displayed as default */
144    private boolean                      isDefaultDisplay;
145
146    /**
147     * The popup menu used to display user choice of actions on data object.
148     */
149    private final JPopupMenu             popupMenu;
150
151    private JSeparator                   separator;
152
153    /** a list of editing GUI components */
154    private List<JMenuItem>              editGUIs;
155
156    /** the list of current selected objects */
157    private List<Object>                 objectsToCopy;
158
159    private JMenu                        exportDatasetMenu;
160
161    private JMenuItem                    addTableMenuItem;
162
163    private JMenuItem                    addDatasetMenuItem;
164
165    private JMenuItem                    addDatatypeMenuItem;
166
167    private JMenuItem                    addLinkMenuItem;
168
169    private JMenuItem                    setLibVerBoundsItem;
170
171    private JMenuItem                    changeIndexItem;
172
173    private String                       currentSearchPhrase = null;
174
175    private boolean                      moveFlag;
176
177    private TreePath[]                   currentSelectionsForMove;
178
179    private boolean                      isApplyBitmaskOnly  = false;
180
181    private int                          currentIndexType;
182
183    private int                          currentIndexOrder;
184
185    private int                          binaryOrder;
186
187    public DefaultTreeView(ViewManager theView) {
188        viewer = theView;
189
190        root = new DefaultMutableTreeNode() {
191            private static final long serialVersionUID = -6829919815424470510L;
192
193            public boolean isLeaf() {
194                return false;
195            }
196        };
197
198        fileList = new Vector<FileFormat>();
199        toolkit = Toolkit.getDefaultToolkit();
200        editGUIs = new Vector<JMenuItem>();
201        objectsToCopy = null;
202        isDefaultDisplay = true;
203        selectedTreePath = null;
204        selectedNode = null;
205        moveFlag = false;
206        currentSelectionsForMove = null;
207
208        addDatasetMenuItem = new JMenuItem("Dataset", ViewProperties.getDatasetIcon());
209        addDatasetMenuItem.addActionListener(this);
210        addDatasetMenuItem.setActionCommand("Add dataset");
211
212        addTableMenuItem = new JMenuItem("Compound DS", ViewProperties.getTableIcon());
213        addTableMenuItem.addActionListener(this);
214        addTableMenuItem.setActionCommand("Add table");
215
216        addDatatypeMenuItem = new JMenuItem("Datatype", ViewProperties.getDatatypeIcon());
217        addDatatypeMenuItem.addActionListener(this);
218        addDatatypeMenuItem.setActionCommand("Add datatype");
219
220        addLinkMenuItem = new JMenuItem("Link", ViewProperties.getLinkIcon());
221        addLinkMenuItem.addActionListener(this);
222        addLinkMenuItem.setActionCommand("Add link");
223
224        setLibVerBoundsItem = new JMenuItem("Set Lib version bounds");
225        setLibVerBoundsItem.addActionListener(this);
226        setLibVerBoundsItem.setActionCommand("Set Lib version bounds");
227
228        changeIndexItem = new JMenuItem("Change file indexing");
229        changeIndexItem.addActionListener(this);
230        changeIndexItem.setActionCommand("Change file indexing");
231
232        // initialize the tree and root
233        treeModel = new DefaultTreeModel(root);
234        tree = new JTree(treeModel);
235
236        tree.setLargeModel(true);
237        tree.setCellRenderer(new HTreeCellRenderer());
238        tree.addMouseListener(new HTreeMouseAdapter());
239        tree.addKeyListener(new HTreeKeyAdapter());
240        tree.setRootVisible(false);
241        // tree.setShowsRootHandles(true);
242        int rowheight = 23 + (int) ((tree.getFont().getSize() - 12) * 0.5);
243        tree.setRowHeight(rowheight);
244
245        // create the separator
246        separator = new JPopupMenu.Separator();
247
248        // create the popupmenu
249        popupMenu = createPopupMenu();
250
251        // reset the scroll increament
252        // layout GUI component
253        this.setLayout(new BorderLayout());
254        this.add(tree, BorderLayout.CENTER);
255    }
256
257    /**
258     * Insert a node into the tree.
259     * 
260     * @param node
261     *            the node to insert.
262     * @param pnode
263     *            the parent node.
264     */
265    private void insertNode(TreeNode node, TreeNode pnode) {
266        if ((node == null) || (pnode == null)) {
267            return;
268        }
269
270        treeModel.insertNodeInto((DefaultMutableTreeNode) node, (DefaultMutableTreeNode) pnode, pnode.getChildCount());
271    }
272
273    /**
274     * Checks if a file is already open.
275     */
276    private boolean isFileOpen(String filename) {
277        boolean isOpen = false;
278
279        // find the file by matching its file name and close the file
280        FileFormat theFile = null;
281        Iterator<FileFormat> iterator = fileList.iterator();
282        while (iterator.hasNext()) {
283            theFile = iterator.next();
284            if (theFile.getFilePath().equals(filename)) {
285                isOpen = true;
286                break;
287            }
288        } // while(iterator.hasNext())
289
290        return isOpen;
291    }
292
293    /** creates a popup menu for a right mouse click on a data object */
294    private JPopupMenu createPopupMenu() {
295        JPopupMenu menu = new JPopupMenu();
296        JMenuItem item;
297
298        item = new JMenuItem("Open");
299        item.setMnemonic(KeyEvent.VK_O);
300        item.addActionListener(this);
301        item.setActionCommand("Open data");
302        menu.add(item);
303
304        item = new JMenuItem("Open As");
305        item.setMnemonic(KeyEvent.VK_A);
306        item.addActionListener(this);
307        item.setActionCommand("Open data as");
308        menu.add(item);
309
310        menu.addSeparator();
311
312        JMenu newOjbectMenu = new JMenu("New");
313        menu.add(newOjbectMenu);
314        editGUIs.add(newOjbectMenu);
315
316        item = new JMenuItem("Group", ViewProperties.getFoldercloseIcon());
317        item.addActionListener(this);
318        item.setActionCommand("Add group");
319        newOjbectMenu.add(item);
320
321        newOjbectMenu.add(addDatasetMenuItem);
322
323        item = new JMenuItem("Image", ViewProperties.getImageIcon());
324        item.addActionListener(this);
325        item.setActionCommand("Add image");
326        newOjbectMenu.add(item);
327
328        newOjbectMenu.add(addTableMenuItem);
329        newOjbectMenu.add(addDatatypeMenuItem);
330        newOjbectMenu.add(addLinkMenuItem);
331
332        menu.addSeparator();
333
334        item = new JMenuItem("Copy");
335        item.setMnemonic(KeyEvent.VK_C);
336        item.addActionListener(this);
337        item.setActionCommand("Copy object");
338        menu.add(item);
339
340        item = new JMenuItem("Paste");
341        item.setMnemonic(KeyEvent.VK_P);
342        item.addActionListener(this);
343        item.setActionCommand("Paste object");
344        menu.add(item);
345        editGUIs.add(item);
346
347        item = new JMenuItem("Delete");
348        item.setMnemonic(KeyEvent.VK_D);
349        item.addActionListener(this);
350        item.setActionCommand("Cut object");
351        menu.add(item);
352        editGUIs.add(item);
353
354        item = new JMenuItem("Cut");
355        item.setMnemonic(KeyEvent.VK_T);
356        item.addActionListener(this);
357        item.setActionCommand("Move object");
358        menu.add(item);
359        editGUIs.add(item);
360        
361        exportDatasetMenu = new JMenu("Export Dataset");
362        menu.add(exportDatasetMenu);
363        item = new JMenuItem("Export Data to Text File");
364        item.addActionListener(this);
365        item.setActionCommand("Save table as text");
366        exportDatasetMenu.add(item);
367    
368        item = new JMenuItem("Export Data as Native Order");
369        item.addActionListener(this);
370        item.setActionCommand("Save table as binary Native Order");
371        exportDatasetMenu.add(item);
372        item = new JMenuItem("Export Data as Little Endian");
373        item.addActionListener(this);
374        item.setActionCommand("Save table as binary Little Endian");
375        exportDatasetMenu.add(item);
376        item = new JMenuItem("Export Data as Big Endian");
377        item.addActionListener(this);
378        item.setActionCommand("Save table as binary Big Endian");
379        exportDatasetMenu.add(item);
380
381        menu.addSeparator();
382
383        item = new JMenuItem("Save to");
384        item.setMnemonic(KeyEvent.VK_S);
385        item.addActionListener(this);
386        item.setActionCommand("Save object to file");
387        menu.add(item);
388
389        item = new JMenuItem("Rename");
390        item.setMnemonic(KeyEvent.VK_R);
391        item.addActionListener(this);
392        item.setActionCommand("Rename object");
393        menu.add(item);
394        editGUIs.add(item);
395
396        menu.addSeparator();
397
398        item = new JMenuItem("Show Properties");
399        item.addActionListener(this);
400        item.setActionCommand("Show object properties");
401        menu.add(item);
402
403        item = new JMenuItem("Show Properties As");
404        item.addActionListener(this);
405        item.setActionCommand("Show object properties as");
406        menu.add(item);
407
408        menu.add(changeIndexItem);
409
410        menu.addSeparator();
411
412        item = new JMenuItem("Find");
413        item.setMnemonic(KeyEvent.VK_F);
414        item.addActionListener(this);
415        item.setActionCommand("Find");
416        menu.add(item);
417
418        // item = new JMenuItem( "Find Next");
419        // item.setMnemonic(KeyEvent.VK_N);
420        // item.addActionListener(this);
421        // item.setActionCommand("Find next");
422        // menu.add(item);
423
424        menu.addSeparator();
425
426        item = new JMenuItem("Expand All");
427        item.addActionListener(this);
428        item.setActionCommand("Expand all");
429        menu.add(item);
430        item = new JMenuItem("Collapse All");
431        item.addActionListener(this);
432        item.setActionCommand("Collapse all");
433        menu.add(item);
434
435        menu.addSeparator();
436
437        item = new JMenuItem("Close File");
438        item.setMnemonic(KeyEvent.VK_E);
439        item.addActionListener(this);
440        item.setActionCommand("Close file");
441        menu.add(item);
442
443        item = new JMenuItem("Reload File");
444        // item.setMnemonic(KeyEvent.VK_R);
445        item.addActionListener(this);
446        item.setActionCommand("Reload file");
447        menu.add(item);
448
449        menu.add(separator);
450        menu.add(setLibVerBoundsItem);
451
452        return menu;
453    }
454
455    /** display the popupmenu of data properties */
456    private void showPopupMenu(MouseEvent e) {
457        int x = e.getX();
458        int y = e.getY();
459
460        HObject selectedObject = ((HObject) (selectedNode.getUserObject()));
461        boolean isReadOnly = selectedObject.getFileFormat().isReadOnly();
462
463        setEnabled(editGUIs, !isReadOnly);
464
465        boolean isWritable = !selectedObject.getFileFormat().isReadOnly();
466        if (selectedObject instanceof Group) {
467            popupMenu.getComponent(0).setEnabled(false); // "open" menuitem
468            popupMenu.getComponent(1).setEnabled(false); // "open as" menuitem
469
470            boolean state = !(((Group) selectedObject).isRoot());
471            popupMenu.getComponent(5).setEnabled(state); // "Copy" menuitem
472            popupMenu.getComponent(6).setEnabled(isWritable); // "Paste"
473            // menuitem
474            popupMenu.getComponent(7).setEnabled(state && isWritable); // "Delete"
475            // menuitem
476            popupMenu.getComponent(11).setEnabled(state); // "save to" menuitem
477            popupMenu.getComponent(12).setEnabled(state && isWritable); // "rename"
478            // menuitem
479            popupMenu.getComponent(8).setEnabled(
480                    (selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)))
481                    && state && isWritable); // "cut" menuitem
482        }
483        else {
484            popupMenu.getComponent(0).setEnabled(true);
485            popupMenu.getComponent(1).setEnabled(true);
486            popupMenu.getComponent(5).setEnabled(true); // "Copy" menuitem
487            popupMenu.getComponent(6).setEnabled(isWritable); // "Paste"
488            // menuitem
489            popupMenu.getComponent(7).setEnabled(isWritable); // "Delete"
490            // menuitem
491            popupMenu.getComponent(11).setEnabled(true); // "save to" menuitem
492            popupMenu.getComponent(12).setEnabled(isWritable); // "rename"
493            // menuitem
494            popupMenu.getComponent(8).setEnabled(
495                    (selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)))
496                    && isWritable); // "cut" menuitem
497        }
498
499        // adding table is only supported by HDF5
500        if ((selectedFile != null) && selectedFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
501            addDatasetMenuItem.setText("Dataset");
502            addTableMenuItem.setVisible(true);
503            addDatatypeMenuItem.setVisible(true);
504            addLinkMenuItem.setVisible(true);
505            boolean state = false;
506            if ((selectedObject instanceof Group)) {
507                state = (((Group) selectedObject).isRoot());
508                separator.setVisible(isWritable && state);
509                setLibVerBoundsItem.setVisible(isWritable && state); 
510                // added only if it is HDF5format, iswritable & isroot
511            }
512            else {
513                separator.setVisible(false);
514                setLibVerBoundsItem.setVisible(false);
515            }
516            changeIndexItem.setVisible(state);
517        }
518        else {
519            addDatasetMenuItem.setText("SDS");
520            addTableMenuItem.setVisible(false);
521            addDatatypeMenuItem.setVisible(false);
522            addLinkMenuItem.setVisible(false);
523            separator.setVisible(false);
524            setLibVerBoundsItem.setVisible(false);
525            changeIndexItem.setVisible(false);
526        }
527    
528        // export table is only supported by HDF5
529        if ((selectedObject != null) && selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
530            if ((selectedObject instanceof Dataset)) {
531                Dataset dataset = (Dataset) selectedObject;
532                if ((dataset instanceof ScalarDS)) {
533                    exportDatasetMenu.setVisible(true);
534                }
535            }
536            else {
537                exportDatasetMenu.setVisible(false);
538            }
539        }
540        else {
541            exportDatasetMenu.setVisible(false);
542        }
543    
544        popupMenu.show((JComponent) e.getSource(), x, y);
545    }
546
547    /** disable/enable GUI components */
548    private static void setEnabled(List<JMenuItem> list, boolean b) {
549        Component item = null;
550        Iterator<JMenuItem> it = list.iterator();
551        while (it.hasNext()) {
552            item = it.next();
553            item.setEnabled(b);
554        }
555    }
556
557    /**
558     * Save the current file into HDF4. Since HDF4 does not support packing. The
559     * source file is copied into the new file with the exact same content.
560     */
561    private final void saveAsHDF4(FileFormat srcFile) {
562        if (srcFile == null) {
563            toolkit.beep();
564            JOptionPane.showMessageDialog(this, "Select a file to save.", "HDFView", JOptionPane.ERROR_MESSAGE);
565            return;
566        }
567
568        JFrame owner = (viewer == null) ? new JFrame() : (JFrame) viewer;
569        String currentDir = srcFile.getParent();
570        NewFileDialog dialog = new NewFileDialog(owner, currentDir, FileFormat.FILE_TYPE_HDF4, getCurrentFiles());
571        // dialog.show();
572
573        if (!dialog.isFileCreated()) {
574            return;
575        }
576
577        String filename = dialog.getFile();
578
579        // since cannot pack hdf4, simple copy the whole phyisical file
580        int length = 0;
581        int bsize = 512;
582        byte[] buffer;
583        BufferedInputStream bi = null;
584        BufferedOutputStream bo = null;
585
586        try {
587            bi = new BufferedInputStream(new FileInputStream(srcFile.getFilePath()));
588        }
589        catch (Exception ex) {
590            toolkit.beep();
591            JOptionPane.showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView", JOptionPane.ERROR_MESSAGE);
592            return;
593        }
594
595        try {
596            bo = new BufferedOutputStream(new FileOutputStream(filename));
597        }
598        catch (Exception ex) {
599            try {
600                bi.close();
601            }
602            catch (Exception ex2) {
603                log.debug("output file force input close:", ex2);
604            }
605            toolkit.beep();
606            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
607            return;
608        }
609
610        buffer = new byte[bsize];
611        try {
612            length = bi.read(buffer, 0, bsize);
613        }
614        catch (Exception ex) {
615            length = 0;
616        }
617        while (length > 0) {
618            try {
619                bo.write(buffer, 0, length);
620                length = bi.read(buffer, 0, bsize);
621            }
622            catch (Exception ex) {
623                length = 0;
624            }
625        }
626
627        try {
628            bo.flush();
629        }
630        catch (Exception ex) {
631                log.debug("output file:", ex);
632        }
633        try {
634            bi.close();
635        }
636        catch (Exception ex) {
637                log.debug("input file:", ex);
638        }
639        try {
640            bo.close();
641        }
642        catch (Exception ex) {
643                log.debug("output file:", ex);
644        }
645
646        try {
647            openFile(filename, FileFormat.WRITE);
648        }
649        catch (Exception ex) {
650            toolkit.beep();
651            JOptionPane .showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView", JOptionPane.ERROR_MESSAGE);
652        }
653    }
654
655    /**
656     * Copy the current file into a new file. The new file does not include the
657     * inaccessible objects. Values of reference dataset are not updated in the
658     * new file.
659     */
660    private void saveAsHDF5(FileFormat srcFile) {
661        if (srcFile == null) {
662            toolkit.beep();
663            JOptionPane.showMessageDialog(this, "Select a file to save.", "HDFView", JOptionPane.ERROR_MESSAGE);
664            return;
665        }
666
667        TreeNode root = srcFile.getRootNode();
668        if (root == null) {
669            toolkit.beep();
670            JOptionPane.showMessageDialog(this, "The file is empty.", "HDFView", JOptionPane.ERROR_MESSAGE);
671            return;
672        }
673
674        JFrame owner = (viewer == null) ? new JFrame() : (JFrame) viewer;
675        NewFileDialog dialog = new NewFileDialog(owner, srcFile.getParent(), FileFormat.FILE_TYPE_HDF5,
676                getCurrentFiles());
677        // dialog.show();
678
679        if (!dialog.isFileCreated()) {
680            return;
681        }
682
683        String filename = dialog.getFile();
684
685        int n = root.getChildCount();
686        Vector<Object> objList = new Vector<Object>(n);
687        DefaultMutableTreeNode node = null;
688        for (int i = 0; i < n; i++) {
689            node = (DefaultMutableTreeNode) root.getChildAt(i);
690            objList.add(node.getUserObject());
691        }
692
693        FileFormat newFile = null;
694        try {
695            newFile = openFile(filename, FileFormat.WRITE);
696        }
697        catch (Exception ex) {
698            toolkit.beep();
699            JOptionPane .showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView", JOptionPane.ERROR_MESSAGE);
700            return;
701        }
702
703        if (newFile == null) {
704            return;
705        }
706
707        TreeNode pnode = newFile.getRootNode();
708
709        pasteObject(objList, pnode, newFile);
710        objList.setSize(0);
711
712        Group srcGroup = (Group) ((DefaultMutableTreeNode) root).getUserObject();
713        Group dstGroup = (Group) ((DefaultMutableTreeNode) newFile.getRootNode()).getUserObject();
714        Object[] parameter = new Object[2];
715        Class<?> classHOjbect = null;
716        Class<?>[] parameterClass = new Class[2];
717        Method method = null;
718
719        // copy attributes of the root group
720        try {
721            parameter[0] = srcGroup;
722            parameter[1] = dstGroup;
723            classHOjbect = Class.forName("hdf.object.HObject");
724            parameterClass[0] = parameterClass[1] = classHOjbect;
725            method = newFile.getClass().getMethod("copyAttributes", parameterClass);
726            method.invoke(newFile, parameter);
727        }
728        catch (Exception ex) {
729            toolkit.beep();
730            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
731        }
732
733        // update reference datasets
734        parameter[0] = srcGroup.getFileFormat();
735        parameter[1] = newFile;
736        parameterClass[0] = parameterClass[1] = parameter[0].getClass();
737        try {
738            method = newFile.getClass().getMethod("updateReferenceDataset", parameterClass);
739            method.invoke(newFile, parameter);
740        }
741        catch (Exception ex) {
742            toolkit.beep();
743            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
744        }
745    }
746
747    /** copy selected objects */
748    private void copyObject() {
749        objectsToCopy = getSelectedObjects();
750        moveFlag = false;
751    }
752
753    /** move selected objects */
754    private void moveObject() {
755        objectsToCopy = getSelectedObjects();
756        moveFlag = true;
757        currentSelectionsForMove = tree.getSelectionPaths();
758    }
759
760    /** paste selected objects */
761    private void pasteObject() {
762        log.trace("pasteObject(): start");
763        if (moveFlag == true) {
764            HObject theObj = null;
765            for (int i = 0; i < currentSelectionsForMove.length; i++) {
766                DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelectionsForMove[i]
767                        .getLastPathComponent());
768                theObj = (HObject) currentNode.getUserObject();
769
770                if (isObjectOpen(theObj)) {
771                    toolkit.beep();
772                    JOptionPane.showMessageDialog(this, "Cannot move the selected object: " + theObj
773                            + "\nThe dataset or dataset in the group is in use."
774                            + "\n\nPlease close the dataset(s) and try again.\n", "HDFView", JOptionPane.ERROR_MESSAGE);
775                    moveFlag = false;
776                    currentSelectionsForMove = null;
777                    objectsToCopy = null;
778                    return;
779                }
780            }
781        }
782
783        TreeNode pnode = selectedNode;
784
785        if ((objectsToCopy == null) || (objectsToCopy.size() <= 0) || (pnode == null)) {
786            return;
787        }
788
789        FileFormat srcFile = ((HObject) objectsToCopy.get(0)).getFileFormat();
790        FileFormat dstFile = getSelectedFile();
791        FileFormat h5file = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
792        FileFormat h4file = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4);
793
794        if (srcFile == null) {
795            toolkit.beep();
796            JOptionPane.showMessageDialog(this, "Source file is null.", "HDFView", JOptionPane.ERROR_MESSAGE);
797            return;
798        }
799        else if (dstFile == null) {
800            toolkit.beep();
801            JOptionPane.showMessageDialog(this, "Destination file is null.", "HDFView", JOptionPane.ERROR_MESSAGE);
802            return;
803        }
804        else if (srcFile.isThisType(h4file) && dstFile.isThisType(h5file)) {
805            toolkit.beep();
806            JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy HDF4 object to HDF5 file",
807                    "HDFView", JOptionPane.ERROR_MESSAGE);
808            return;
809        }
810        else if (srcFile.isThisType(h5file) && dstFile.isThisType(h4file)) {
811            toolkit.beep();
812            JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy HDF5 object to HDF4 file",
813                    "HDFView", JOptionPane.ERROR_MESSAGE);
814            return;
815        }
816
817        if (moveFlag == true) {
818            if (srcFile != dstFile) {
819                toolkit.beep();
820                JOptionPane.showMessageDialog(this, "Cannot move the selected object to different file", "HDFView",
821                        JOptionPane.ERROR_MESSAGE);
822                moveFlag = false;
823                currentSelectionsForMove = null;
824                objectsToCopy = null;
825                return;
826            }
827        }
828
829        if (pnode.isLeaf()) {
830            pnode = pnode.getParent();
831        }
832        Group pgroup = (Group) ((DefaultMutableTreeNode) pnode).getUserObject();
833        String fullPath = pgroup.getPath() + pgroup.getName();
834        if (pgroup.isRoot()) {
835            fullPath = HObject.separator;
836        }
837
838        String msg = "";
839        int msgType = JOptionPane.QUESTION_MESSAGE;
840        if (srcFile.isThisType(h4file)) {
841            msg = "WARNING: object can not be deleted after it is copied.\n\n";
842            msgType = JOptionPane.WARNING_MESSAGE;
843        }
844
845        msg += "Do you want to copy the selected object(s) to \nGroup: " + fullPath + "\nFile: "
846                + dstFile.getFilePath();
847
848        int op = -1;
849        if (moveFlag == true) {
850            String moveMsg = "Do you want to move the selected object(s) to \nGroup: " + fullPath + "\nFile: "
851                    + dstFile.getFilePath();
852            op = JOptionPane.showConfirmDialog(this, moveMsg, "Move object", JOptionPane.YES_NO_OPTION, msgType);
853        }
854        else {
855            op = JOptionPane.showConfirmDialog(this, msg, "Copy object", JOptionPane.YES_NO_OPTION, msgType);
856        }
857
858        log.trace("pasteObject(): op={}", op);
859        if (op == JOptionPane.NO_OPTION) {
860            return;
861        }
862
863        pasteObject(objectsToCopy, pnode, dstFile);
864
865        // objectsToCopy = null;
866        if (moveFlag == true) {
867            removeSelectedObjects();
868            moveFlag = false;
869            currentSelectionsForMove = null;
870            objectsToCopy = null;
871        }
872        log.trace("pasteObject(): finish");
873    }
874
875    /** paste selected objects */
876    private void pasteObject(List<Object> objList, TreeNode pnode, FileFormat dstFile) {
877        if ((objList == null) || (objList.size() <= 0) || (pnode == null)) {
878            return;
879        }
880
881        ((HObject) objList.get(0)).getFileFormat();
882        Group pgroup = (Group) ((DefaultMutableTreeNode) pnode).getUserObject();
883        log.trace("pasteObject(...): start");
884
885        HObject theObj = null;
886        TreeNode newNode = null;
887        Iterator<Object> iterator = objList.iterator();
888        while (iterator.hasNext()) {
889            newNode = null;
890            theObj = (HObject) iterator.next();
891
892            if ((theObj instanceof Group) && ((Group) theObj).isRoot()) {
893                toolkit.beep();
894                JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy the root group", "HDFView",
895                        JOptionPane.ERROR_MESSAGE);
896                return;
897            }
898
899            // check if it creates infinite loop
900            Group pg = pgroup;
901            while (!pg.isRoot()) {
902                if (theObj.equals(pg)) {
903                    toolkit.beep();
904                    JOptionPane.showMessageDialog(this, "Unsupported operation: cannot copy a group to itself.",
905                            "HDFView", JOptionPane.ERROR_MESSAGE);
906                    return;
907                }
908                pg = pg.getParent();
909            }
910
911            try {
912                log.trace("pasteObject(...): dstFile.copy(theObj, pgroup, null)");
913                newNode = dstFile.copy(theObj, pgroup, null);
914            }
915            catch (Exception ex) {
916                toolkit.beep();
917                JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
918                // newNode = null;
919            }
920
921            // add the node to the tree
922            if (newNode != null) {
923                insertNode(newNode, pnode);
924            }
925
926        } // while (iterator.hasNext())
927        log.trace("pasteObject(...): finish");
928    }
929
930    private void removeSelectedObjects() {
931        FileFormat theFile = getSelectedFile();
932        if (theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
933            toolkit.beep();
934            JOptionPane.showMessageDialog(this, "Unsupported operation: cannot delete HDF4 object.", "HDFView",
935                    JOptionPane.ERROR_MESSAGE);
936            return;
937        }
938
939        TreePath[] currentSelections = tree.getSelectionPaths();
940
941        if (moveFlag == true) {
942            currentSelections = currentSelectionsForMove;
943        }
944        if ((currentSelections == null) || (currentSelections.length <= 0)) {
945            return;
946        }
947        if (moveFlag != true) {
948            int op = JOptionPane.showConfirmDialog(this, "Do you want to remove all the selected object(s) ?",
949                    "Remove object", JOptionPane.YES_NO_OPTION);
950
951            if (op == JOptionPane.NO_OPTION) {
952                return;
953            }
954        }
955        HObject theObj = null;
956        for (int i = 0; i < currentSelections.length; i++) {
957            DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelections[i].getLastPathComponent());
958            theObj = (HObject) currentNode.getUserObject();
959
960            // cannot delete root
961            if (theObj instanceof Group) {
962                Group g = (Group) theObj;
963                if (g.isRoot()) {
964                    toolkit.beep();
965                    JOptionPane.showMessageDialog(this, "Unsupported operation: cannot delete the file root.",
966                            "HDFView", JOptionPane.ERROR_MESSAGE);
967                    return;
968                }
969            }
970
971            if (moveFlag != true) {
972                if (isObjectOpen(theObj)) {
973                    toolkit.beep();
974                    JOptionPane.showMessageDialog(this, "Cannot delete the selected object: " + theObj
975                            + "\nThe dataset or dataset in the group is in use."
976                            + "\n\nPlease close the dataset(s) and try again.\n", "HDFView", JOptionPane.ERROR_MESSAGE);
977                    continue;
978                }
979            }
980
981            try {
982                theFile.delete(theObj);
983            }
984            catch (Exception ex) {
985                toolkit.beep();
986                JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
987                continue;
988            }
989
990            if (theObj.equals(selectedObject)) {
991                selectedObject = null;
992            }
993
994            removeNode(currentNode);
995        } // for (int i=0; i< currentSelections.length; i++) {
996    }
997
998    private void removeNode(DefaultMutableTreeNode node) {
999        if (node == null) {
1000            return;
1001        }
1002
1003        DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) (node.getParent());
1004        if (parentNode != null) {
1005            treeModel.removeNodeFromParent(node);
1006
1007            // add the two lines to fix bug in HDFView 1.2. Delete a subgroup
1008            // and
1009            // then copy the group to another group, the deleted group still
1010            // exists.
1011            Group pgroup = (Group) parentNode.getUserObject();
1012            pgroup.removeFromMemberList((HObject) node.getUserObject());
1013
1014            if (node.equals(selectedNode)) {
1015                selectedNode = null;
1016                selectedFile = null;
1017            }
1018        } // if (parentNode != null) {
1019    }
1020
1021    private boolean isObjectOpen(HObject obj) {
1022        boolean isOpen = false;
1023
1024        if (obj instanceof Group) {
1025            Group g = (Group) obj;
1026            List<?> members = g.getMemberList();
1027            if ((members == null) || (members.size() == 0)) {
1028                isOpen = false;
1029            }
1030            else {
1031                int n = members.size();
1032                for (int i = 0; i < n; i++) {
1033                    HObject theObj = (HObject) members.get(i);
1034                    isOpen = (viewer.getDataView(theObj) != null);
1035                    if (isOpen) {
1036                        break;
1037                    }
1038                }
1039            }
1040        }
1041        else {
1042            if (viewer.getDataView(obj) == null) {
1043                isOpen = false;
1044            }
1045            else {
1046                isOpen = true;
1047            }
1048        }
1049
1050        return isOpen;
1051    }
1052
1053    /**
1054     * Returns a list of all user objects that traverses the subtree rooted at
1055     * this node in breadth-first order..
1056     * 
1057     * @param node
1058     *            the node to start with.
1059     */
1060    private final List<Object> breadthFirstUserObjects(TreeNode node) {
1061        if (node == null) {
1062            return null;
1063        }
1064
1065        Vector<Object> list = new Vector<Object>();
1066        DefaultMutableTreeNode theNode = null;
1067        Enumeration<?> local_enum = ((DefaultMutableTreeNode) node).breadthFirstEnumeration();
1068        while (local_enum.hasMoreElements()) {
1069            theNode = (DefaultMutableTreeNode) local_enum.nextElement();
1070            list.add(theNode.getUserObject());
1071        }
1072
1073        return list;
1074    }
1075
1076    /**
1077     * Find first object that is matched by name.
1078     * 
1079     * @param objName
1080     *            -- the object name.
1081     * @return the object if found, otherwise, returns null.
1082     */
1083    private final static HObject find(String objName, TreePath treePath, JTree tree) {
1084        HObject retObj = null;
1085        boolean isFound = false, isPrefix = false, isSuffix = false, isContain = false;
1086
1087        if (objName == null || objName.length() <= 0 || treePath == null) {
1088            return null;
1089        }
1090
1091        if (objName.equals("*")) return null;
1092
1093        if (objName.startsWith("*")) {
1094            isSuffix = true;
1095            objName = objName.substring(1, objName.length());
1096        }
1097
1098        if (objName.endsWith("*")) {
1099            isPrefix = true;
1100            objName = objName.substring(0, objName.length() - 1);
1101        }
1102
1103        if (isPrefix && isSuffix) {
1104            isContain = true;
1105            isPrefix = isSuffix = false;
1106        }
1107
1108        if (objName == null || objName.length() <= 0) return null;
1109
1110        DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
1111        if (node == null) return null;
1112
1113        HObject obj = null;
1114        String theName = null;
1115        DefaultMutableTreeNode theNode = null;
1116        Enumeration<?> local_enum = node.breadthFirstEnumeration();
1117        while (local_enum.hasMoreElements()) {
1118            theNode = (DefaultMutableTreeNode) local_enum.nextElement();
1119            obj = (HObject) theNode.getUserObject();
1120            if (obj != null && (theName = obj.getName()) != null) {
1121                if (isPrefix)
1122                    isFound = theName.startsWith(objName);
1123                else if (isSuffix)
1124                    isFound = theName.endsWith(objName);
1125                else if (isContain)
1126                    isFound = theName.contains(objName);
1127                else
1128                    isFound = theName.equals(objName);
1129
1130                if (isFound) {
1131                    retObj = obj;
1132                    break;
1133                }
1134            }
1135        }
1136
1137        if (retObj != null) {
1138            TreePath dstPath = getTreePath(treePath, theNode, 0);
1139
1140            // tree.fireTreeExpanded(dstPath) ;
1141            tree.setSelectionPath(dstPath);
1142            tree.scrollPathToVisible(dstPath);
1143        }
1144
1145        return retObj;
1146    }
1147
1148    /**
1149     * Get the TreePath from the parent to the target node.
1150     * 
1151     * @param parent
1152     *            -- the parent TreePath
1153     * @param node
1154     *            -- the target node
1155     * @param depth
1156     * @return the tree path if target node found, otherwise; returns null;
1157     */
1158    private static TreePath getTreePath(TreePath parent, TreeNode node, int depth) {
1159        if (node == null || parent == null || depth < 0) return null;
1160
1161        TreeNode theNode = (TreeNode) parent.getLastPathComponent();
1162        if (node == theNode) return parent;
1163
1164        if (theNode.getChildCount() >= 0) {
1165            for (Enumeration<?> e = theNode.children(); e.hasMoreElements();) {
1166                TreeNode n = (TreeNode) e.nextElement();
1167                TreePath path = parent.pathByAddingChild(n);
1168                TreePath result = getTreePath(path, node, depth + 1);
1169
1170                if (result != null) {
1171                    return result;
1172                }
1173            }
1174        }
1175
1176        return null;
1177    }
1178
1179    private void addGroup() {
1180        if ((selectedObject == null) || (selectedNode == null)) {
1181            return;
1182        }
1183
1184        Group pGroup = null;
1185        if (selectedObject instanceof Group) {
1186            pGroup = (Group) selectedObject;
1187        }
1188        else {
1189            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1190        }
1191
1192        NewGroupDialog dialog = new NewGroupDialog((JFrame) viewer, pGroup, 
1193                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1194        dialog.setVisible(true);
1195
1196        HObject obj = (HObject) dialog.getObject();
1197        if (obj == null) {
1198            return;
1199        }
1200
1201        Group pgroup = dialog.getParentGroup();
1202        try {
1203            this.addObject(obj, pgroup);
1204        }
1205        catch (Exception ex) {
1206            toolkit.beep();
1207            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1208            return;
1209        }
1210    }
1211
1212    private void addDataset() {
1213        if ((selectedObject == null) || (selectedNode == null)) {
1214            return;
1215        }
1216
1217        Group pGroup = null;
1218        if (selectedObject instanceof Group) {
1219            pGroup = (Group) selectedObject;
1220        }
1221        else {
1222            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1223        }
1224
1225        NewDatasetDialog dialog = new NewDatasetDialog((JFrame) viewer, pGroup, 
1226                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1227        dialog.setVisible(true);
1228
1229        HObject obj = (HObject) dialog.getObject();
1230        if (obj == null) {
1231            return;
1232        }
1233
1234        Group pgroup = dialog.getParentGroup();
1235        try {
1236            addObject(obj, pgroup);
1237        }
1238        catch (Exception ex) {
1239            toolkit.beep();
1240            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1241            return;
1242        }
1243    }
1244
1245    private void addImage() {
1246        if ((selectedObject == null) || (selectedNode == null)) {
1247            return;
1248        }
1249
1250        Group pGroup = null;
1251        if (selectedObject instanceof Group) {
1252            pGroup = (Group) selectedObject;
1253        }
1254        else {
1255            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1256        }
1257
1258        NewImageDialog dialog = new NewImageDialog((JFrame) viewer, pGroup, breadthFirstUserObjects(selectedObject
1259                .getFileFormat().getRootNode()));
1260        dialog.setVisible(true);
1261
1262        HObject obj = (HObject) dialog.getObject();
1263        if (obj == null) {
1264            return;
1265        }
1266
1267        Group pgroup = dialog.getParentGroup();
1268        try {
1269            this.addObject(obj, pgroup);
1270        }
1271        catch (Exception ex) {
1272            toolkit.beep();
1273            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1274            return;
1275        }
1276    }
1277
1278    private void addTable() {
1279        if ((selectedObject == null) || (selectedNode == null)) {
1280            return;
1281        }
1282
1283        Group pGroup = null;
1284        if (selectedObject instanceof Group) {
1285            pGroup = (Group) selectedObject;
1286        }
1287        else {
1288            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1289        }
1290
1291        NewTableDataDialog dialog = new NewTableDataDialog((JFrame) viewer, pGroup,
1292                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1293        dialog.setVisible(true);
1294
1295        HObject obj = (HObject) dialog.getObject();
1296        if (obj == null) {
1297            return;
1298        }
1299
1300        Group pgroup = dialog.getParentGroup();
1301        try {
1302            addObject(obj, pgroup);
1303        }
1304        catch (Exception ex) {
1305            toolkit.beep();
1306            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1307            return;
1308        }
1309    }
1310
1311    private void addDatatype() {
1312        if ((selectedObject == null) || (selectedNode == null)) {
1313            return;
1314        }
1315
1316        Group pGroup = null;
1317        if (selectedObject instanceof Group) {
1318            pGroup = (Group) selectedObject;
1319        }
1320        else {
1321            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1322        }
1323
1324        NewDatatypeDialog dialog = new NewDatatypeDialog((JFrame) viewer, pGroup,
1325                breadthFirstUserObjects(selectedObject.getFileFormat().getRootNode()));
1326        dialog.setVisible(true);
1327
1328        HObject obj = (HObject) dialog.getObject();
1329        if (obj == null) {
1330            return;
1331        }
1332
1333        Group pgroup = dialog.getParentGroup();
1334        try {
1335            addObject(obj, pgroup);
1336        }
1337        catch (Exception ex) {
1338            toolkit.beep();
1339            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1340            return;
1341        }
1342    }
1343
1344    private void addLink() {
1345        if ((selectedObject == null) || (selectedNode == null)) {
1346            return;
1347        }
1348
1349        Group pGroup = null;
1350        if (selectedObject instanceof Group) {
1351            pGroup = (Group) selectedObject;
1352        }
1353        else {
1354            pGroup = (Group) ((DefaultMutableTreeNode) selectedNode.getParent()).getUserObject();
1355        }
1356
1357        NewLinkDialog dialog = new NewLinkDialog((JFrame) viewer, pGroup, breadthFirstUserObjects(selectedObject
1358                .getFileFormat().getRootNode()));
1359        dialog.setVisible(true);
1360
1361        HObject obj = (HObject) dialog.getObject();
1362        if (obj == null) {
1363            return;
1364        }
1365
1366        Group pgroup = dialog.getParentGroup();
1367        try {
1368            addObject(obj, pgroup);
1369        }
1370        catch (Exception ex) {
1371            toolkit.beep();
1372            JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1373            return;
1374        }
1375    }
1376
1377    /** Save data as file. */
1378    private void saveAsFile() throws Exception {
1379        if (!(selectedObject instanceof Dataset) || (selectedObject == null) || (selectedNode == null)) {
1380            return;
1381        }
1382        Dataset dataset = (Dataset) selectedObject;
1383        final JFileChooser fchooser = new JFileChooser(dataset.getFile());
1384        fchooser.setFileFilter(DefaultFileFilter.getFileFilterText());
1385        // fchooser.changeToParentDirectory();
1386        File choosedFile = null;
1387        
1388        if(binaryOrder == 99) {
1389            fchooser.setDialogTitle("Save Dataset Data To Text File --- " + dataset.getName());
1390    
1391            choosedFile = new File(dataset.getName() + ".txt");
1392        }
1393        else {
1394            fchooser.setDialogTitle("Save Current Data To Binary File --- " + dataset.getName());
1395
1396            choosedFile = new File(dataset.getName() + ".bin");
1397        }
1398
1399        fchooser.setSelectedFile(choosedFile);
1400        int returnVal = fchooser.showSaveDialog(this);
1401
1402        if (returnVal != JFileChooser.APPROVE_OPTION) {
1403            return;
1404        }
1405
1406        choosedFile = fchooser.getSelectedFile();
1407        if (choosedFile == null) {
1408            return;
1409        }
1410        String fname = choosedFile.getAbsolutePath();
1411
1412        // check if the file is in use
1413        List<?> fileList = viewer.getTreeView().getCurrentFiles();
1414        if (fileList != null) {
1415            FileFormat theFile = null;
1416            Iterator<?> iterator = fileList.iterator();
1417            while (iterator.hasNext()) {
1418                theFile = (FileFormat) iterator.next();
1419                if (theFile.getFilePath().equals(fname)) {
1420                    toolkit.beep();
1421                    JOptionPane.showMessageDialog(this, 
1422                            "Unable to save data to file \"" + fname + "\". \nThe file is being used.", 
1423                            "Export Dataset", JOptionPane.ERROR_MESSAGE);
1424                    return;
1425                }
1426            }
1427        }
1428
1429        if (choosedFile.exists()) {
1430            int newFileFlag = JOptionPane.showConfirmDialog(this, 
1431                    "File exists. Do you want to replace it ?",
1432                    "Export Dataset", JOptionPane.YES_NO_OPTION);
1433            if (newFileFlag == JOptionPane.NO_OPTION) {
1434                return;
1435            }
1436        }
1437
1438        boolean isH4 = selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));
1439
1440        if (isH4) {
1441            toolkit.beep();
1442            JOptionPane.showMessageDialog(this, "Cannot export HDF4 object.", "HDFView", JOptionPane.ERROR_MESSAGE);
1443            return;
1444        }
1445
1446        try {
1447            selectedObject.getFileFormat().exportDataset(fname, dataset.getFile(), dataset.getFullName(), binaryOrder);
1448        }
1449        catch (Exception ex) {
1450            toolkit.beep();
1451            JOptionPane.showMessageDialog(this, ex.getMessage(), "HDFView", JOptionPane.ERROR_MESSAGE);
1452        }
1453
1454        viewer.showStatus("Data save to: " + fname);
1455    }
1456
1457    private void renameObject() {
1458        if (selectedObject == null) {
1459            return;
1460        }
1461
1462        if ((selectedObject instanceof Group) && ((Group) selectedObject).isRoot()) {
1463            toolkit.beep();
1464            JOptionPane.showMessageDialog(this, "Cannot rename the root.", "HDFView", JOptionPane.ERROR_MESSAGE);
1465            return;
1466        }
1467
1468        boolean isH4 = selectedObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));
1469
1470        if (isH4) {
1471            toolkit.beep();
1472            JOptionPane.showMessageDialog(this, "Cannot rename HDF4 object.", "HDFView", JOptionPane.ERROR_MESSAGE);
1473            return;
1474        }
1475
1476        String oldName = selectedObject.getName();
1477        String newName = (String) JOptionPane.showInputDialog(this, "Rename \"" + oldName + "\" to:", "Rename...",
1478                JOptionPane.INFORMATION_MESSAGE, null, null, oldName);
1479
1480        if (newName == null) {
1481            return;
1482        }
1483
1484        newName = newName.trim();
1485        if ((newName == null) || (newName.length() == 0) || newName.equals(oldName)) {
1486            return;
1487        }
1488
1489        try {
1490            selectedObject.setName(newName);
1491        }
1492        catch (Exception ex) {
1493            toolkit.beep();
1494            JOptionPane.showMessageDialog(this, ex.getMessage(), "HDFView", JOptionPane.ERROR_MESSAGE);
1495        }
1496    }
1497
1498    @SuppressWarnings("rawtypes")
1499    private void setLibVersionBounds() {
1500        Object[] lowValues = { "Earliest", "Latest" };
1501        Object[] highValues = { "Latest" };
1502        JComboBox lowComboBox = new JComboBox(lowValues);
1503        lowComboBox.setName("earliestversion");
1504        JComboBox highComboBox = new JComboBox(highValues);
1505        highComboBox.setName("latestversion");
1506
1507        Object[] msg = { "Earliest Version:", lowComboBox, "Latest Version:", highComboBox };
1508        Object[] options = { "Ok", "Cancel" };
1509        JOptionPane op = new JOptionPane(msg, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options);
1510
1511        op.setName("libselect");
1512        JDialog dialog = op.createDialog(this, "Set the library version bounds: ");
1513        dialog.setVisible(true);
1514
1515        String result = null;
1516        try {
1517            result = (String) op.getValue();
1518        }
1519        catch (Exception err) {
1520            // err.printStackTrace();
1521        }
1522
1523        if ((result != null) && (result.equals("Ok"))) {
1524            int low = -1;
1525            int high = 1;
1526            if ((lowComboBox.getSelectedItem()).equals("Earliest"))
1527                low = 0;
1528            else
1529                low = 1;
1530            try {
1531                selectedObject.getFileFormat().setLibBounds(low, high);
1532            }
1533            catch (Throwable err) {
1534                toolkit.beep();
1535                JOptionPane.showMessageDialog(this, err, "Error when setting lib version bounds",
1536                        JOptionPane.ERROR_MESSAGE);
1537                return;
1538            }
1539        }
1540        else
1541            return;
1542    }
1543
1544    // Implementing java.io.ActionListener
1545    public void actionPerformed(ActionEvent e) {
1546        String cmd = e.getActionCommand();
1547
1548        if (cmd.equals("Close file")) {
1549            ((HDFView) viewer).actionPerformed(e);
1550        }
1551        else if (cmd.equals("Reload file")) {
1552            ((HDFView) viewer).actionPerformed(e);
1553        }
1554        else if (cmd.equals("Add group")) {
1555            addGroup();
1556        }
1557        else if (cmd.equals("Add dataset")) {
1558            addDataset();
1559        }
1560        else if (cmd.equals("Add image")) {
1561            addImage();
1562        }
1563        else if (cmd.equals("Add table")) {
1564            addTable();
1565        }
1566        else if (cmd.equals("Add datatype")) {
1567            addDatatype();
1568        }
1569        else if (cmd.equals("Add link")) {
1570            addLink();
1571        }
1572        else if (cmd.equals("Save table as text")) {
1573            binaryOrder = 99;
1574            try {
1575                saveAsFile();
1576            }
1577            catch (Exception ex) {
1578                toolkit.beep();
1579                JOptionPane.showMessageDialog((JFrame) viewer, ex, "Export Dataset", JOptionPane.ERROR_MESSAGE);
1580            }
1581        }
1582        else if (cmd.startsWith("Save table as binary")) {
1583            if (cmd.equals("Save table as binary Native Order")) binaryOrder = 1;
1584            if (cmd.equals("Save table as binary Little Endian")) binaryOrder = 2;
1585            if (cmd.equals("Save table as binary Big Endian")) binaryOrder = 3;
1586            try {
1587                saveAsFile();
1588            }
1589            catch (Exception ex) {
1590                toolkit.beep();
1591                JOptionPane.showMessageDialog((JFrame) viewer, ex, "Export Dataset", JOptionPane.ERROR_MESSAGE);
1592            }
1593        }
1594        else if (cmd.startsWith("Open data")) {
1595            if (cmd.equals("Open data")) {
1596                isDefaultDisplay = true;
1597            }
1598            else {
1599                isDefaultDisplay = false;
1600            }
1601
1602            try {
1603                showDataContent(selectedObject);
1604            }
1605            catch (Throwable err) {
1606                toolkit.beep();
1607                JOptionPane.showMessageDialog(this, err, "HDFView", JOptionPane.ERROR_MESSAGE);
1608                return;
1609            }
1610        }
1611        else if (cmd.equals("Copy object")) {
1612            copyObject();
1613        }
1614        else if (cmd.equals("Paste object")) {
1615            pasteObject();
1616        }
1617        else if (cmd.equals("Cut object")) {
1618            removeSelectedObjects();
1619        }
1620        else if (cmd.equals("Move object")) {
1621            moveObject();
1622        }
1623        else if (cmd.equals("Save object to file")) {
1624            if (selectedObject == null) {
1625                return;
1626            }
1627
1628            if ((selectedObject instanceof Group) && ((Group) selectedObject).isRoot()) {
1629                toolkit.beep();
1630                JOptionPane.showMessageDialog(this,
1631                        "Cannot save the root group.\nUse \"Save As\" from file menu to save the whole file",
1632                        "HDFView", JOptionPane.ERROR_MESSAGE);
1633                return;
1634            }
1635
1636            String filetype = FileFormat.FILE_TYPE_HDF4;
1637            boolean isH5 = selectedObject.getFileFormat().isThisType(
1638                    FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
1639            if (isH5) {
1640                filetype = FileFormat.FILE_TYPE_HDF5;
1641            }
1642
1643            NewFileDialog dialog = new NewFileDialog((JFrame) viewer, selectedObject.getFileFormat().getParent(),
1644                    filetype, fileList);
1645            // dialog.show();
1646
1647            if (!dialog.isFileCreated()) {
1648                return;
1649            }
1650
1651            String filename = dialog.getFile();
1652            FileFormat dstFile = null;
1653            try {
1654                dstFile = openFile(filename, FileFormat.WRITE);
1655            }
1656            catch (Exception ex) {
1657                toolkit.beep();
1658                JOptionPane.showMessageDialog(this, ex.getMessage() + "\n" + filename, "HDFView",
1659                        JOptionPane.ERROR_MESSAGE);
1660            }
1661            List<Object> objList = new Vector<Object>(2);
1662            objList.add(selectedObject);
1663            pasteObject(objList, dstFile.getRootNode(), dstFile);
1664        }
1665        else if (cmd.equals("Rename object")) {
1666            renameObject();
1667        }
1668        else if (cmd.startsWith("Show object properties")) {
1669            if (cmd.equals("Show object properties")) {
1670                isDefaultDisplay = true;
1671            }
1672            else {
1673                isDefaultDisplay = false;
1674            }
1675
1676            try {
1677                showMetaData(selectedObject);
1678            }
1679            catch (Exception ex) {
1680                toolkit.beep();
1681                JOptionPane.showMessageDialog(this, ex, "HDFView", JOptionPane.ERROR_MESSAGE);
1682            }
1683        }
1684        else if (cmd.startsWith("Find")) {
1685            if (cmd.equals("Find")) {
1686                String findStr = currentSearchPhrase;
1687                if (findStr == null) findStr = "";
1688
1689                findStr = (String) JOptionPane.showInputDialog(this, "Find (e.g. O3Quality, O3*, or *Quality):",
1690                        "Find Object by Name", JOptionPane.PLAIN_MESSAGE, null, null, findStr);
1691
1692                if (findStr != null && findStr.length() > 0) currentSearchPhrase = findStr;
1693            }
1694
1695            find(currentSearchPhrase, selectedTreePath, tree);
1696        }
1697        else if (cmd.startsWith("Expand all")) {
1698            int row = 0;
1699            while (row < tree.getRowCount()) {
1700                tree.expandRow(row);
1701                row++;
1702            }
1703        }
1704        else if (cmd.startsWith("Collapse all")) {
1705            int row = tree.getRowCount() - 1;
1706            while (row >= 0) {
1707                tree.collapseRow(row);
1708                row--;
1709            }
1710        }
1711        else if (cmd.startsWith("Set Lib version bounds")) {
1712            setLibVersionBounds();
1713        }
1714        else if (cmd.startsWith("Change file indexing")) {
1715            ChangeIndexingDialog dialog = new ChangeIndexingDialog((JFrame) viewer, selectedFile);
1716            dialog.setVisible(true);
1717            if (dialog.isreloadFile()) {
1718                selectedFile.setIndexType(dialog.getIndexType());
1719                selectedFile.setIndexOrder(dialog.getIndexOrder());
1720                ((HDFView) viewer).reloadFile();
1721            }
1722        }
1723    }
1724
1725    public FileFormat reopenFile(FileFormat fileFormat) throws Exception {
1726        if (fileFormat.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
1727            this.currentIndexType = fileFormat.getIndexType(null);
1728            this.currentIndexOrder = fileFormat.getIndexOrder(null);
1729        }
1730        if (fileFormat.isReadOnly())
1731            return openFile(fileFormat.getAbsolutePath(), FileFormat.READ);
1732        else
1733            return openFile(fileFormat.getAbsolutePath(), FileFormat.WRITE);
1734    }
1735    
1736    /**
1737     * Opens a file and retrieves the file structure of the file. It also can be
1738     * used to create a new file by setting the accessID to FileFormat.CREATE.
1739     * 
1740     * <p>
1741     * Subclasses must implement this function to take appropriate steps to open
1742     * a file.
1743     * </p>
1744     * 
1745     * @param filename
1746     *            the name of the file to open.
1747     * @param accessID
1748     *            identifier for the file access. Valid value of accessID is:
1749     *            <ul>
1750     *            <li>FileFormat.READ --- allow read-only access to file.</li>
1751     *            <li>FileFormat.WRITE --- allow read and write access to file.</li>
1752     *            <li>FileFormat.CREATE --- create a new file.</li>
1753     *            </ul>
1754     * 
1755     * @return the FileFormat of this file if successful; otherwise returns
1756     *         null.
1757     */
1758    public FileFormat openFile(String filename, int accessID) throws Exception {
1759        FileFormat fileFormat = null;
1760        MutableTreeNode fileRoot = null;
1761        boolean bNewFile = (FileFormat.OPEN_NEW == (accessID & FileFormat.OPEN_NEW));
1762        if(bNewFile)
1763            accessID = accessID - FileFormat.OPEN_NEW;
1764        
1765        if (isFileOpen(filename)) {
1766            viewer.showStatus("File is in use");
1767            return null;
1768            // throw new UnsupportedOperationException("File is in use.");
1769        }
1770
1771        File tmpFile = new File(filename);
1772        if (!tmpFile.exists()) {
1773            throw new UnsupportedOperationException("File does not exist.");
1774        }
1775
1776        if (!tmpFile.canWrite()) {
1777            accessID = FileFormat.READ;
1778        }
1779
1780        Enumeration<?> keys = FileFormat.getFileFormatKeys();
1781
1782        String theKey = null;
1783        while (keys.hasMoreElements()) {
1784            theKey = (String) keys.nextElement();
1785            if (theKey.equals(FileFormat.FILE_TYPE_HDF4)) {
1786                try {
1787                    FileFormat h4format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4);
1788                    if ((h4format != null) && h4format.isThisType(filename)) {
1789                        fileFormat = h4format.createInstance(filename, accessID);
1790                        break;
1791                    }
1792                }
1793                catch (Throwable err) {
1794                        log.debug("retrieves the file structure of {}:", filename, err);
1795                }
1796                continue;
1797            }
1798            else if (theKey.equals(FileFormat.FILE_TYPE_HDF5)) {
1799                try {
1800                    FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
1801                    if ((h5format != null) && h5format.isThisType(filename)) {
1802                        fileFormat = h5format.createInstance(filename, accessID);
1803                        break;
1804                    }
1805                }
1806                catch (Throwable err) {
1807                        log.debug("retrieves the file structure of {}:", filename, err);
1808                }
1809                continue;
1810            }
1811            else {
1812                try {
1813
1814                    FileFormat theformat = FileFormat.getFileFormat(theKey);
1815                    if (theformat.isThisType(filename)) {
1816                        fileFormat = theformat.createInstance(filename, accessID);
1817                        break;
1818                    }
1819                }
1820                catch (Throwable err) {
1821                        log.debug("retrieves the file structure of {}:", filename, err);
1822                }
1823            }
1824        }
1825
1826        if (fileFormat == null) {
1827            throw new java.io.IOException("Unsupported fileformat - " + filename);
1828        }
1829
1830        ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1831        try {
1832            fileFormat.setMaxMembers(ViewProperties.getMaxMembers());
1833            fileFormat.setStartMembers(ViewProperties.getStartMembers());
1834            if (fileFormat.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
1835                if(bNewFile) {
1836                    currentIndexType = fileFormat.getIndexType(ViewProperties.getIndexType());
1837                    currentIndexOrder = fileFormat.getIndexOrder(ViewProperties.getIndexOrder());                  
1838                }
1839                fileFormat.setIndexType(currentIndexType);
1840                fileFormat.setIndexOrder(currentIndexOrder);
1841            }
1842
1843            fileFormat.open();
1844        }
1845        catch (Exception ex) {
1846                log.debug("fileformat init and open:", ex);
1847                fileFormat = null;
1848        }
1849        finally {
1850            ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1851        }
1852
1853        if (fileFormat == null) {
1854            throw new java.io.IOException("Failed to open file - " + filename);
1855        } 
1856        else  {
1857            fileRoot = (MutableTreeNode) fileFormat.getRootNode();
1858            if (fileRoot != null) {
1859                insertNode(fileRoot, root);
1860
1861                int currentRowCount = tree.getRowCount();
1862                if (currentRowCount > 0) {
1863                    tree.expandRow(tree.getRowCount() - 1);
1864                }
1865
1866                fileList.add(fileFormat);
1867            }           
1868        }
1869
1870        return fileFormat;
1871    }
1872
1873    /**
1874     * close a file
1875     * 
1876     * @param file
1877     *            the file to close
1878     */
1879    public void closeFile(FileFormat file) throws Exception {
1880        if (file == null) {
1881            return;
1882        }
1883
1884        // find the file node in the tree and removed it from the tree first
1885        FileFormat theFile = null;
1886        DefaultMutableTreeNode theNode = null;
1887        Enumeration<?> enumeration = root.children();
1888        while (enumeration.hasMoreElements()) {
1889            theNode = (DefaultMutableTreeNode) enumeration.nextElement();
1890            Group g = (Group) theNode.getUserObject();
1891            theFile = g.getFileFormat();
1892
1893            if (theFile.equals(file)) {
1894                treeModel.removeNodeFromParent(theNode);
1895                try {
1896                    theFile.close();
1897                }
1898                catch (Exception ex) {
1899                        log.debug("close {}:", theFile.getFilePath(), ex);
1900                }
1901                fileList.remove(theFile);
1902                if (theFile.equals(selectedFile)) {
1903                    selectedFile = null;
1904                    selectedNode = null;
1905                }
1906                break;
1907            }
1908        } // while(enumeration.hasMoreElements())
1909    }
1910
1911    /**
1912     * save a file
1913     * 
1914     * @param file
1915     *            the file to save
1916     */
1917    public void saveFile(FileFormat file) throws Exception {
1918        if (file == null) {
1919            toolkit.beep();
1920            JOptionPane.showMessageDialog(this, "Select a file to save.", "HDFView", JOptionPane.ERROR_MESSAGE);
1921            return;
1922        }
1923
1924        boolean isH4 = file.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4));
1925        boolean isH5 = file.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5));
1926
1927        if (!(isH4 || isH5)) {
1928            toolkit.beep();
1929            JOptionPane.showMessageDialog(this, "Saving file is not supported for this file type", "HDFView",
1930                    JOptionPane.ERROR_MESSAGE);
1931            return;
1932        }
1933
1934        // write the change of the data into file before save the file
1935        List<?> views = ((HDFView) viewer).getDataViews();
1936        Object theView = null;
1937        TableView tableView = null;
1938        TextView textView = null;
1939        FileFormat theFile = null;
1940        if (views != null) {
1941            int n = views.size();
1942            for (int i = 0; i < n; i++) {
1943                theView = views.get(i);
1944                if (theView instanceof TableView) {
1945                    tableView = (TableView) theView;
1946                    theFile = tableView.getDataObject().getFileFormat();
1947                    if (file.equals(theFile)) {
1948                        tableView.updateValueInFile();
1949                    }
1950                }
1951                else if (theView instanceof TextView) {
1952                    textView = (TextView) theView;
1953                    theFile = textView.getDataObject().getFileFormat();
1954                    if (file.equals(theFile)) {
1955                        textView.updateValueInFile();
1956                    }
1957                }
1958            }
1959        }
1960
1961        if (isH5) {
1962            saveAsHDF5(file);
1963        }
1964        else if (isH4) {
1965            saveAsHDF4(file);
1966        }
1967    }
1968
1969    /**
1970     * Gets the selected the file. When multiple files are open, we need to know
1971     * which file is currently selected.
1972     * 
1973     * @return the FileFormat of the selected file.
1974     */
1975    public FileFormat getSelectedFile() {
1976        return selectedFile;
1977    }
1978
1979    /**
1980     * Gets a list of selected object in the tree. Obtaining a list of current
1981     * selected objects is necessary for copy/paste/delete objects.
1982     * 
1983     * @return a list of selected object in the tree.
1984     */
1985    public List<Object> getSelectedObjects() {
1986        TreePath[] paths = tree.getSelectionPaths();
1987        if ((paths == null) || (paths.length <= 0)) {
1988            return null;
1989        }
1990
1991        List<Object> objs = new Vector<Object>(paths.length);
1992        HObject theObject = null, parentObject;
1993        DefaultMutableTreeNode currentNode = null, parentNode = null;
1994        for (int i = 0; i < paths.length; i++) {
1995            currentNode = (DefaultMutableTreeNode) (paths[i].getLastPathComponent());
1996            theObject = (HObject) currentNode.getUserObject();
1997
1998            if (theObject != null) {
1999                objs.add(theObject);
2000                // removed the group from the selected list if some of its
2001                // members are selected
2002                // to avoid duplicated copy/paste when a group is pasted.
2003                parentNode = (DefaultMutableTreeNode) currentNode.getParent();
2004                parentObject = (HObject) parentNode.getUserObject();
2005                objs.remove(parentObject);
2006            }
2007        }
2008
2009        return objs;
2010    }
2011
2012    /**
2013     * @return the current selected object in the tree.
2014     */
2015    public HObject getCurrentObject() {
2016        return selectedObject;
2017    }
2018
2019    /**
2020     * Display the content of a data object.
2021     * 
2022     * @param dataObject
2023     *            the data object
2024     * @return the DataView that displays the data content
2025     * @throws Exception
2026     */
2027    public DataView showDataContent(HObject dataObject) throws Exception {
2028        log.trace("showDataContent: start");
2029
2030        if ((dataObject == null) || !(dataObject instanceof Dataset)) {
2031            return null; // can only display dataset
2032        }
2033
2034        Dataset d = (Dataset) dataObject;
2035
2036        if (d.getRank() <= 0) {
2037            d.init();
2038        }
2039        boolean isText = ((d instanceof ScalarDS) && ((ScalarDS) d).isText());
2040        boolean isImage = ((d instanceof ScalarDS) && ((ScalarDS) d).isImage());
2041        boolean isDisplayTypeChar = false;
2042        boolean isTransposed = false;
2043        boolean isIndexBase1 = ViewProperties.isIndexBase1();
2044        BitSet bitmask = null;
2045        String dataViewName = null;
2046        log.trace("showDataContent: inited");
2047
2048        JInternalFrame theFrame = (JInternalFrame) viewer.getDataView(d);
2049
2050        if (isDefaultDisplay) {
2051
2052            if (theFrame != null) {
2053                theFrame.toFront();
2054                return null;
2055            }
2056
2057            if (isText) {
2058                dataViewName = (String) HDFView.getListOfTextView().get(0);
2059            }
2060            else if (isImage) {
2061                dataViewName = (String) HDFView.getListOfImageView().get(0);
2062            }
2063            else {
2064                dataViewName = (String) HDFView.getListOfTableView().get(0);
2065            }
2066        }
2067        else {
2068            DataOptionDialog dialog = new DataOptionDialog(viewer, d);
2069
2070            dialog.setVisible(true);
2071            if (dialog.isCancelled()) {
2072                return null;
2073            }
2074
2075            isImage = dialog.isImageDisplay();
2076            isDisplayTypeChar = dialog.isDisplayTypeChar();
2077            dataViewName = dialog.getDataViewName();
2078            isTransposed = dialog.isTransposed();
2079            bitmask = dialog.getBitmask();
2080            isIndexBase1 = dialog.isIndexBase1();
2081            isApplyBitmaskOnly = dialog.isApplyBitmaskOnly();
2082        }
2083        log.trace("showDataContent: {}", dataViewName);
2084
2085        // enables use of JHDF5 in JNLP (Web Start) applications, the system
2086        // class loader with reflection first.
2087        Class<?> theClass = null;
2088        try {
2089            theClass = Class.forName(dataViewName);
2090        }
2091        catch (Exception ex) {
2092            try {
2093                theClass = ViewProperties.loadExtClass().loadClass(dataViewName);
2094            }
2095            catch (Exception ex2) {
2096                theClass = null;
2097            }
2098        }
2099
2100        // use default dataview
2101        if (theClass == null) {
2102            log.trace("showDataContent: use default dataview");
2103            if (isText)
2104                dataViewName = "hdf.view.DefaultTextView";
2105            else if (isImage)
2106                dataViewName = "hdf.view.DefaultImageView";
2107            else
2108                dataViewName = "hdf.view.DefaultTableView";
2109            try {
2110                theClass = Class.forName(dataViewName);
2111            }
2112            catch (Exception ex) {
2113                log.debug("Class.forName {} failure: ", dataViewName, ex);
2114            }
2115        }
2116        Object theView = null;
2117        Object[] initargs = { viewer };
2118        HashMap<DATA_VIEW_KEY, Serializable> map = new HashMap<DATA_VIEW_KEY, Serializable>(8);
2119        map.put(ViewProperties.DATA_VIEW_KEY.INDEXBASE1, new Boolean(isIndexBase1));
2120        if (bitmask != null) {
2121            map.put(ViewProperties.DATA_VIEW_KEY.BITMASK, bitmask);
2122            if (isApplyBitmaskOnly) map.put(ViewProperties.DATA_VIEW_KEY.BITMASKOP, ViewProperties.BITMASK_OP.AND);
2123
2124            // create a copy of dataset
2125            ScalarDS d_copy = null;
2126            Constructor<? extends Dataset> constructor = null;
2127            Object[] paramObj = null;
2128            try {
2129                Class<?>[] paramClass = { FileFormat.class, String.class, String.class, long[].class };
2130                constructor = d.getClass().getConstructor(paramClass);
2131
2132                paramObj = new Object[] { d.getFileFormat(), d.getName(), d.getPath(), d.getOID() };
2133            }
2134            catch (Exception ex) {
2135                constructor = null;
2136            }
2137
2138            try {
2139                d_copy = (ScalarDS) constructor.newInstance(paramObj);
2140            }
2141            catch (Exception ex) {
2142                d_copy = null;
2143            }
2144            if (d_copy != null) {
2145                try {
2146                    d_copy.init();
2147                    log.trace("showDataContent: d_copy inited");
2148                    int rank = d.getRank();
2149                    System.arraycopy(d.getDims(), 0, d_copy.getDims(), 0, rank);
2150                    System.arraycopy(d.getStartDims(), 0, d_copy.getStartDims(), 0, rank);
2151                    System.arraycopy(d.getSelectedDims(), 0, d_copy.getSelectedDims(), 0, rank);
2152                    System.arraycopy(d.getStride(), 0, d_copy.getStride(), 0, rank);
2153                    System.arraycopy(d.getSelectedIndex(), 0, d_copy.getSelectedIndex(), 0, 3);
2154                }
2155                catch (Throwable ex) {
2156                    ex.printStackTrace();
2157                }
2158
2159                map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, d_copy);
2160            }
2161        }
2162        if (dataViewName.startsWith("hdf.view.DefaultTableView")) {
2163            map.put(ViewProperties.DATA_VIEW_KEY.CHAR, new Boolean(isDisplayTypeChar));
2164            map.put(ViewProperties.DATA_VIEW_KEY.TRANSPOSED, new Boolean(isTransposed));
2165            Object[] tmpargs = { viewer, map };
2166            initargs = tmpargs;
2167        }
2168        else if (dataViewName.startsWith("hdf.view.DefaultImageView")) {
2169            map.put(ViewProperties.DATA_VIEW_KEY.CONVERTBYTE, new Boolean((bitmask != null)));
2170            Object[] tmpargs = { viewer, map };
2171            initargs = tmpargs;
2172        }
2173
2174        ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
2175        try {
2176            theView = Tools.newInstance(theClass, initargs);
2177            log.trace("showDataContent: Tools.newInstance");
2178
2179            viewer.addDataView((DataView) theView);
2180        }
2181        finally {
2182            ((JFrame) viewer).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
2183        }
2184
2185        log.trace("showDataContent: finish");
2186        return (DataView) theView;
2187    }
2188
2189    /**
2190     * Displays the meta data of a data object.
2191     * 
2192     * @param dataObject
2193     *            the data object
2194     * @return the MetaDataView that displays the MetaData of the data object
2195     * @throws Exception
2196     */
2197    public MetaDataView showMetaData(HObject dataObject) throws Exception {
2198        if (dataObject == null) {
2199            return null;
2200        }
2201
2202        List<?> metaDataViewList = HDFView.getListOfMetaDataView();
2203        if ((metaDataViewList == null) || (metaDataViewList.size() <= 0)) {
2204            return null;
2205        }
2206
2207        int n = metaDataViewList.size();
2208        String className = (String) metaDataViewList.get(0);
2209
2210        if (!isDefaultDisplay && (n > 1)) {
2211            className = (String) JOptionPane.showInputDialog(this, "Select MetaDataView", "HDFView",
2212                    JOptionPane.INFORMATION_MESSAGE, null, metaDataViewList.toArray(), className);
2213        }
2214
2215        // enables use of JHDF5 in JNLP (Web Start) applications, the system
2216        // class loader with reflection first.
2217        Class<?> theClass = null;
2218        try {
2219            theClass = Class.forName(className);
2220        }
2221        catch (Exception ex) {
2222            theClass = ViewProperties.loadExtClass().loadClass(className);
2223        }
2224
2225        Object[] initargs = { viewer };
2226        MetaDataView dataView = (MetaDataView) Tools.newInstance(theClass, initargs);
2227
2228        return dataView;
2229    }
2230
2231    /**
2232     * Adds a new data object to the file.
2233     * 
2234     * @param newObject
2235     *            the new object to add.
2236     * @param parentGroup
2237     *            the parent group the object is to add to.
2238     * @throws Exception
2239     */
2240    public void addObject(HObject newObject, Group parentGroup) throws Exception {
2241        if ((newObject == null) || (parentGroup == null)) {
2242            return;
2243        }
2244
2245        TreeNode pnode = findTreeNode(parentGroup);
2246        TreeNode newnode = null;
2247        if (newObject instanceof Group) {
2248            newnode = new DefaultMutableTreeNode(newObject) {
2249                private static final long serialVersionUID = -8852535261445958398L;
2250
2251                public boolean isLeaf() {
2252                    return false;
2253                }
2254            };
2255        }
2256        else {
2257            newnode = new DefaultMutableTreeNode(newObject);
2258        }
2259
2260        treeModel.insertNodeInto((DefaultMutableTreeNode) newnode, (DefaultMutableTreeNode) pnode,
2261                pnode.getChildCount());
2262    }
2263
2264    /**
2265     * Returns the JTree which holds the file structure.
2266     * 
2267     * @return the JTree which holds the file structure.
2268     */
2269    public JTree getTree() {
2270        return tree;
2271    }
2272
2273    /**
2274     * Returns the list of current open files..
2275     */
2276    public List<FileFormat> getCurrentFiles() {
2277        return fileList;
2278    }
2279
2280    /**
2281     * Returns the tree node that contains the given data object.
2282     */
2283    public TreeNode findTreeNode(HObject obj) {
2284        if (obj == null) {
2285            return null;
2286        }
2287
2288        TreeNode theFileRoot = obj.getFileFormat().getRootNode();
2289        if (theFileRoot == null) {
2290            return null;
2291        }
2292
2293        DefaultMutableTreeNode theNode = null;
2294        HObject theObj = null;
2295        Enumeration<?> local_enum = ((DefaultMutableTreeNode) theFileRoot).breadthFirstEnumeration();
2296        while (local_enum.hasMoreElements()) {
2297            theNode = (DefaultMutableTreeNode) local_enum.nextElement();
2298            theObj = (HObject) theNode.getUserObject();
2299            if (theObj == null) {
2300                continue;
2301            }
2302            else if (theObj.equals(obj)) {
2303                return theNode;
2304            }
2305        }
2306
2307        return null;
2308    }
2309
2310    /**
2311     * This class is used to change the default icons for tree nodes.
2312     * 
2313     * @see javax.swing.tree.DefaultTreeCellRenderer
2314     */
2315    private class HTreeCellRenderer extends DefaultTreeCellRenderer {
2316        private static final long serialVersionUID = -9030708781106435297L;
2317        private Icon              h4Icon, h5Icon, datasetIcon, imageIcon, tableIcon, textIcon, openFolder, closeFolder,
2318        datasetIconA, imageIconA, tableIconA, textIconA, openFolderA, closeFolderA, datatypeIcon,
2319        datatypeIconA, questionIcon;
2320
2321        private HTreeCellRenderer() {
2322            super();
2323
2324            openFolder = ViewProperties.getFolderopenIcon();
2325            closeFolder = ViewProperties.getFoldercloseIcon();
2326            datasetIcon = ViewProperties.getDatasetIcon();
2327            imageIcon = ViewProperties.getImageIcon();
2328            h4Icon = ViewProperties.getH4Icon();
2329            h5Icon = ViewProperties.getH5Icon();
2330            tableIcon = ViewProperties.getTableIcon();
2331            textIcon = ViewProperties.getTextIcon();
2332
2333            openFolderA = ViewProperties.getFolderopenIconA();
2334            closeFolderA = ViewProperties.getFoldercloseIconA();
2335            datasetIconA = ViewProperties.getDatasetIconA();
2336            imageIconA = ViewProperties.getImageIconA();
2337            tableIconA = ViewProperties.getTableIconA();
2338            textIconA = ViewProperties.getTextIconA();
2339            datatypeIcon = ViewProperties.getDatatypeIcon();
2340            datatypeIconA = ViewProperties.getDatatypeIconA();
2341
2342            questionIcon = ViewProperties.getQuestionIcon();
2343
2344            if (openFolder != null) {
2345                openIcon = openFolder;
2346            }
2347            else {
2348                openFolder = this.openIcon;
2349            }
2350
2351            if (closeFolder != null) {
2352                closedIcon = closeFolder;
2353            }
2354            else {
2355                closeFolder = closedIcon;
2356            }
2357
2358            if (datasetIcon == null) {
2359                datasetIcon = leafIcon;
2360            }
2361            if (imageIcon == null) {
2362                imageIcon = leafIcon;
2363            }
2364            if (tableIcon == null) {
2365                tableIcon = leafIcon;
2366            }
2367            if (textIcon == null) {
2368                textIcon = leafIcon;
2369            }
2370            if (h4Icon == null) {
2371                h4Icon = leafIcon;
2372            }
2373            if (h5Icon == null) {
2374                h5Icon = leafIcon;
2375            }
2376            if (datatypeIcon == null) {
2377                datatypeIcon = leafIcon;
2378            }
2379
2380            if (questionIcon == null) {
2381                questionIcon = leafIcon;
2382            }
2383
2384            if (openFolderA == null) {
2385                openFolderA = openFolder;
2386            }
2387            if (closeFolderA == null) {
2388                closeFolderA = closeFolder;
2389            }
2390            if (datasetIconA == null) {
2391                datasetIconA = datasetIcon;
2392            }
2393            if (imageIconA == null) {
2394                imageIconA = imageIcon;
2395            }
2396            if (tableIconA == null) {
2397                tableIconA = tableIcon;
2398            }
2399            if (textIconA == null) {
2400                textIconA = textIcon;
2401            }
2402            if (datatypeIconA == null) {
2403                datatypeIconA = datatypeIcon;
2404            }
2405        }
2406
2407        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
2408                boolean leaf, int row, boolean hasFocus) {
2409            HObject theObject = (HObject) ((DefaultMutableTreeNode) value).getUserObject();
2410            
2411            if (theObject == null)
2412                return super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
2413
2414            boolean hasAttribute = theObject.hasAttribute();
2415            
2416            if (theObject instanceof Dataset) {
2417                if (theObject instanceof ScalarDS) {
2418                    ScalarDS sd = (ScalarDS) theObject;
2419                    if (sd.isImage()) {
2420                        if (hasAttribute) {
2421                            leafIcon = imageIconA;
2422                        }
2423                        else {
2424                            leafIcon = imageIcon;
2425                        }
2426                    }
2427                    else if (sd.isText()) {
2428                        if (hasAttribute) {
2429                            leafIcon = textIconA;
2430                        }
2431                        else {
2432                            leafIcon = textIcon;
2433                        }
2434                    }
2435                    else {
2436                        if (hasAttribute) {
2437                            leafIcon = datasetIconA;
2438                        }
2439                        else {
2440                            leafIcon = datasetIcon;
2441                        }
2442
2443                    }
2444                }
2445                else if (theObject instanceof CompoundDS) {
2446                    if (hasAttribute) {
2447                        leafIcon = tableIconA;
2448                    }
2449                    else {
2450                        leafIcon = tableIcon;
2451                    }
2452                }
2453            }
2454            else if (theObject instanceof Group) {
2455                Group g = (Group) theObject;
2456
2457                if (hasAttribute) {
2458                    openIcon = openFolderA;
2459                    closedIcon = closeFolderA;
2460                }
2461                else {
2462                    openIcon = openFolder;
2463                    closedIcon = closeFolder;
2464                }
2465
2466                if (g.isRoot()) {
2467                    if (g.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))) {
2468                        openIcon = closedIcon = h5Icon;
2469                    }
2470                    else if (g.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))) {
2471                        openIcon = closedIcon = h4Icon;
2472                    }
2473                }
2474            }
2475            else if (theObject instanceof Datatype) {
2476                Datatype t = (Datatype) theObject;
2477
2478                if (hasAttribute) {
2479                    leafIcon = datatypeIconA;
2480                }
2481                else {
2482                    leafIcon = datatypeIcon;
2483                }
2484            }
2485
2486            else {
2487                leafIcon = questionIcon;
2488            }
2489
2490            return super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
2491        }
2492    } // private class HTreeCellRenderer
2493
2494    /**
2495     * Handle mouse clicks on data object in the tree view. A right mouse-click
2496     * to show the popup menu for user choice. A double left-mouse-click to
2497     * display the data content. A single left-mouse-click to select the current
2498     * data object.
2499     */
2500    private class HTreeMouseAdapter extends MouseAdapter {
2501        // public void mousePressed(MouseEvent e)
2502        public void mouseReleased(MouseEvent e) {
2503            TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
2504            if (selPath == null) {
2505                return;
2506            }
2507
2508            DefaultMutableTreeNode theNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
2509            if (!theNode.equals(selectedNode)) {
2510                selectedTreePath = selPath;
2511                selectedNode = theNode;
2512                selectedObject = ((HObject) (selectedNode.getUserObject()));
2513                FileFormat theFile = selectedObject.getFileFormat();
2514                if ((theFile != null) && !theFile.equals(selectedFile)) {
2515                    // a different file is selected, handle only one file a time
2516                    selectedFile = theFile;
2517                    tree.clearSelection();
2518                    tree.setSelectionPath(selPath);
2519                }
2520
2521                viewer.mouseEventFired(e);
2522            }
2523
2524            // ***************************************************************
2525            // Different platforms have different ways to show popups
2526            // if (e.getModifiers() == MouseEvent.BUTTON3_MASK) works for all
2527            // but mac
2528            // mouseReleased() and e.isPopupTrigger() work on windows and mac
2529            // but not unix,
2530            // mouseClicked() and e.isPopupTrigger() work on unix and mac but
2531            // not windows,
2532            // to solve the problem, we use both.
2533            // 7/25/06 bug 517. e.isPopupTrigger does not work on one mouse Mac.
2534            // add (MouseEvent.BUTTON1_MASK|MouseEvent.CTRL_MASK) for MAC
2535            int eMod = e.getModifiers();
2536            if (e.isPopupTrigger()
2537                    || (eMod == MouseEvent.BUTTON3_MASK)
2538                    || (System.getProperty("os.name").startsWith("Mac") && (eMod == (MouseEvent.BUTTON1_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())))) {
2539                int selRow = tree.getRowForLocation(e.getX(), e.getY());
2540
2541                if (!tree.isRowSelected(selRow)) {
2542                    // reselect the node
2543                    tree.clearSelection();
2544                    tree.setSelectionRow(selRow);
2545                }
2546                showPopupMenu(e);
2547            }
2548            // double click to open data content
2549            else if (e.getClickCount() == 2) {
2550                isDefaultDisplay = true;
2551                try {
2552                    showDataContent(selectedObject);
2553                }
2554                catch (Exception ex) {
2555                }
2556            }
2557        } // public void mousePressed(MouseEvent e)
2558    } // private class HTreeMouseAdapter extends MouseAdapter
2559
2560    /**
2561     * Handle key pressed event.
2562     */
2563    private class HTreeKeyAdapter extends KeyAdapter {
2564
2565        @Override
2566        public void keyTyped(KeyEvent e) {
2567        }
2568
2569        @Override
2570        public void keyPressed(KeyEvent e) {
2571        }
2572
2573        @Override
2574        public void keyReleased(KeyEvent e) {
2575            int key = e.getKeyCode();
2576            if (key == KeyEvent.VK_KP_LEFT || key == KeyEvent.VK_KP_RIGHT || key == KeyEvent.VK_KP_UP
2577                    || key == KeyEvent.VK_KP_DOWN || key == KeyEvent.VK_LEFT || key == KeyEvent.VK_RIGHT
2578                    || key == KeyEvent.VK_UP || key == KeyEvent.VK_DOWN) {
2579
2580                TreePath selPath = ((JTree) e.getComponent()).getSelectionPath();
2581                if (selPath == null) {
2582                    return;
2583                }
2584
2585                DefaultMutableTreeNode theNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
2586
2587                if (!theNode.equals(selectedNode)) {
2588                    selectedTreePath = selPath;
2589                    selectedNode = theNode;
2590                    selectedObject = ((HObject) (selectedNode.getUserObject()));
2591                    FileFormat theFile = selectedObject.getFileFormat();
2592                    if ((theFile != null) && !theFile.equals(selectedFile)) {
2593                        // a different file is selected, handle only one file a
2594                        // time
2595                        selectedFile = theFile;
2596                        tree.clearSelection();
2597                        tree.setSelectionPath(selPath);
2598                    }
2599
2600                    ((HDFView) viewer).showMetaData(selectedObject);
2601                }
2602            }
2603        }
2604    }
2605
2606    /**
2607     * ChangeIndexingDialog displays file index options.
2608     */
2609    private class ChangeIndexingDialog extends JDialog implements ActionListener {
2610        private static final long serialVersionUID = 1048114401768228742L;
2611    
2612        private JRadioButton checkIndexType;
2613        private JRadioButton checkIndexOrder;
2614        private JRadioButton checkIndexNative;
2615    
2616        private boolean reloadFile;
2617        
2618        private FileFormat selectedFile;
2619        private int indexType;
2620        private int indexOrder;
2621    
2622        /**
2623         * constructs an UserOptionsDialog.
2624         * 
2625         * @param view
2626         *            The HDFView.
2627         */
2628        private ChangeIndexingDialog(JFrame view, FileFormat viewSelectedFile) {
2629            super(view, "Index Options", true);
2630    
2631            selectedFile = viewSelectedFile;
2632            indexType = selectedFile.getIndexType(null);
2633            indexOrder = selectedFile.getIndexOrder(null);
2634            reloadFile = false;
2635    
2636            JPanel contentPane = (JPanel) getContentPane();
2637            contentPane.setLayout(new BorderLayout(8, 8));
2638            contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5));
2639    
2640            JPanel indexP = new JPanel();
2641            TitledBorder tborder = new TitledBorder("Index Options");
2642            tborder.setTitleColor(Color.darkGray);
2643            indexP.setBorder(tborder);
2644            indexP.setLayout(new GridLayout(2, 1, 10, 10));
2645            indexP.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
2646            contentPane.add(indexP);
2647    
2648            JPanel pType = new JPanel();
2649            tborder = new TitledBorder("Indexing Type");
2650            tborder.setTitleColor(Color.darkGray);
2651            pType.setBorder(tborder);
2652            pType.setLayout(new GridLayout(1, 2, 8, 8));
2653            checkIndexType = new JRadioButton("By Name", (indexType) == selectedFile.getIndexType("H5_INDEX_NAME"));
2654            checkIndexType.setName("Index by Name");
2655            pType.add(checkIndexType);
2656            JRadioButton checkIndexCreateOrder = new JRadioButton("By Creation Order", (indexType) == selectedFile.getIndexType("H5_INDEX_CRT_ORDER"));
2657            checkIndexCreateOrder.setName("Index by Creation Order");
2658            pType.add(checkIndexCreateOrder);
2659            ButtonGroup bTypegrp = new ButtonGroup();
2660            bTypegrp.add(checkIndexType);
2661            bTypegrp.add(checkIndexCreateOrder);
2662            indexP.add(pType);
2663    
2664            JPanel pOrder = new JPanel();
2665            tborder = new TitledBorder("Indexing Order");
2666            tborder.setTitleColor(Color.darkGray);
2667            pOrder.setBorder(tborder);
2668            pOrder.setLayout(new GridLayout(1, 3, 8, 8));
2669            checkIndexOrder = new JRadioButton("Increments", (indexOrder) == selectedFile.getIndexOrder("H5_ITER_INC"));
2670            checkIndexOrder.setName("Index Increments");
2671            pOrder.add(checkIndexOrder);
2672            JRadioButton checkIndexDecrement = new JRadioButton("Decrements", (indexOrder) == selectedFile.getIndexOrder("H5_ITER_DEC"));
2673            checkIndexDecrement.setName("Index Decrements");
2674            pOrder.add(checkIndexDecrement);
2675            checkIndexNative = new JRadioButton("Native", (indexOrder) == selectedFile.getIndexOrder("H5_ITER_NATIVE"));
2676            checkIndexNative.setName("Index Native");
2677            pOrder.add(checkIndexNative);
2678            ButtonGroup bOrdergrp = new ButtonGroup();
2679            bOrdergrp.add(checkIndexOrder);
2680            bOrdergrp.add(checkIndexDecrement);
2681            bOrdergrp.add(checkIndexNative);
2682            indexP.add(pOrder);
2683    
2684            JPanel buttonP = new JPanel();
2685            JButton b = new JButton("Reload File");
2686            b.setName("Reload File");
2687            b.setActionCommand("Reload File");
2688            b.addActionListener(this);
2689            buttonP.add(b);
2690            b = new JButton("Cancel");
2691            b.setName("Cancel");
2692            b.setActionCommand("Cancel");
2693            b.addActionListener(this);
2694            buttonP.add(b);
2695    
2696            contentPane.add("Center", indexP);
2697            contentPane.add("South", buttonP);
2698    
2699            // locate the parent dialog
2700            Point l = getParent().getLocation();
2701            l.x += 250;
2702            l.y += 80;
2703            setLocation(l);
2704            validate();
2705            pack();
2706        }
2707    
2708        public void setVisible(boolean b) {
2709            super.setVisible(b);
2710        }
2711    
2712        public void actionPerformed(ActionEvent e) {
2713            String cmd = e.getActionCommand();
2714    
2715            if (cmd.equals("Reload File")) {
2716                setIndexOptions();
2717                setVisible(false);
2718            }
2719            else if (cmd.equals("Cancel")) {
2720                reloadFile = false;
2721                setVisible(false);
2722            }
2723        }
2724    
2725        private void setIndexOptions() {
2726            if (checkIndexType.isSelected())
2727                selectedFile.setIndexType(selectedFile.getIndexType("H5_INDEX_NAME"));
2728            else
2729                selectedFile.setIndexType(selectedFile.getIndexType("H5_INDEX_CRT_ORDER"));
2730            indexType = selectedFile.getIndexType(null);
2731            
2732            if (checkIndexOrder.isSelected())
2733                selectedFile.setIndexOrder(selectedFile.getIndexOrder("H5_ITER_INC"));
2734            else if (checkIndexNative.isSelected())
2735                selectedFile.setIndexOrder(selectedFile.getIndexOrder("H5_ITER_NATIVE"));
2736            else
2737                selectedFile.setIndexOrder(selectedFile.getIndexOrder("H5_ITER_DEC"));
2738            indexOrder = selectedFile.getIndexOrder(null);
2739            
2740            reloadFile = true;
2741        }
2742    
2743        public int getIndexType() {
2744            return indexType;
2745        }
2746    
2747        public int getIndexOrder() {
2748            return indexOrder;
2749        }
2750    
2751        public boolean isreloadFile() {
2752            return reloadFile;
2753        }
2754    }
2755}