    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 https://support.hdfgroup.org/products/licenses.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.dialog;
    016
    017import java.io.File;
    018import java.util.ArrayList;
    019import java.util.Iterator;
    020import java.util.LinkedList;
    021import java.util.List;
    022import java.util.Queue;
    023import java.util.Vector;
    024
    025import org.eclipse.swt.SWT;
    026import org.eclipse.swt.custom.CCombo;
    027import org.eclipse.swt.events.DisposeEvent;
    028import org.eclipse.swt.events.DisposeListener;
    029import org.eclipse.swt.events.SelectionAdapter;
    030import org.eclipse.swt.events.SelectionEvent;
    031import org.eclipse.swt.events.TraverseEvent;
    032import org.eclipse.swt.events.TraverseListener;
    033import org.eclipse.swt.graphics.Font;
    034import org.eclipse.swt.graphics.Point;
    035import org.eclipse.swt.graphics.Rectangle;
    036import org.eclipse.swt.layout.GridData;
    037import org.eclipse.swt.layout.GridLayout;
    038import org.eclipse.swt.widgets.Button;
    039import org.eclipse.swt.widgets.Combo;
    040import org.eclipse.swt.widgets.Composite;
    041import org.eclipse.swt.widgets.Dialog;
    042import org.eclipse.swt.widgets.Display;
    043import org.eclipse.swt.widgets.FileDialog;
    044import org.eclipse.swt.widgets.Label;
    045import org.eclipse.swt.widgets.Shell;
    046import org.eclipse.swt.widgets.Text;
    047
    048import hdf.hdf5lib.H5;
    049import hdf.object.FileFormat;
    050import hdf.object.Group;
    051import hdf.object.HObject;
    052import hdf.view.DefaultFileFilter;
    053import hdf.view.Tools;
    054import hdf.view.ViewProperties;
    055
    056/**
    057 * NewLinkDialog shows a message dialog requesting user input for creating
    058 * new links.
    059 *
    060 * @author Jordan T. Henderson
    061 * @version 2.4 1/1/2016
    062 */
    063public class NewLinkDialog extends Dialog {
    064
    065    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewLinkDialog.class);
    066
    067    private Shell         shell;
    068
    069    private Font          curFont;
    070
    071    private Text          nameField;
    072
    073    private Combo         parentChoice;
    074
    075    private CCombo        targetObject;
    076
    077    private String        currentDir;
    078
    079    private Text          targetFile;
    080
    081    private Button        targetFileButton;
    082
    083    private Button        hardLink, softLink, externalLink;
    084
    085    /** a list of current groups */
    086    private List<Group>   groupList;
    087
    088    /** a list of current objects */
    089    private List<?>       objList;
    090
    091    private HObject       newObject;
    092    private Group         parentGroup;
    093
    094    private FileFormat    fileFormat;
    095
    096    private final List<?> fileList;
    097
    098    /**
    099     * Constructs a NewLinkDialog with specified list of possible parent groups.
    100     *
    101     * @param parent
    102     *            the parent shell of the dialog
    103     * @param pGroup
    104     *            the parent group which the new group is added to.
    105     * @param objs
    106     *            the list of all objects.
    107     * @param files
    108     *            the list of all files open in the TreeView
    109     */
    110    public NewLinkDialog(Shell parent, Group pGroup, List<?> objs, List<FileFormat> files) {
    111        super(parent, SWT.APPLICATION_MODAL);
    112
    113        try {
    114            curFont = new Font(
    115                    Display.getCurrent(),
    116                    ViewProperties.getFontType(),
    117                    ViewProperties.getFontSize(),
    118                    SWT.NORMAL);
    119        }
    120        catch (Exception ex) {
    121            curFont = null;
    122        }
    123
    124        newObject = null;
    125        parentGroup = pGroup;
    126        objList = objs;
    127
    128        fileFormat = pGroup.getFileFormat();
    129        currentDir = ViewProperties.getWorkDir();
    130        fileList = files;
    131    }
    132
    133    public void open() {
    134        Shell parent = getParent();
    135        shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL);
    136        shell.setFont(curFont);
    137        shell.setText("New Link...");
    138        shell.setImage(ViewProperties.getHdfIcon());
    139        shell.setLayout(new GridLayout(1, true));
    140
    141        // Create the main content region
    142        Composite content = new Composite(shell, SWT.NONE);
    143        content.setLayout(new GridLayout(2, false));
    144        content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    145
    146        Label label = new Label(content, SWT.LEFT);
    147        label.setFont(curFont);
    148        label.setText("Link name: ");
    149
    150        nameField = new Text(content, SWT.SINGLE | SWT.BORDER);
    151        nameField.setFont(curFont);
    152        GridData fieldData = new GridData(SWT.FILL, SWT.FILL, true, false);
    153        fieldData.minimumWidth = 300;
    154        nameField.setLayoutData(fieldData);
    155
    156        label = new Label(content, SWT.LEFT);
    157        label.setFont(curFont);
    158        label.setText("Parent group: ");
    159
    160        parentChoice = new Combo(content, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY);
    161        parentChoice.setFont(curFont);
    162        parentChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    163        parentChoice.addSelectionListener(new SelectionAdapter() {
    164            @Override
    165            public void widgetSelected(SelectionEvent e) {
    166                parentGroup = groupList.get(parentChoice.getSelectionIndex());
    167            }
    168        });
    169
    170        Composite helpComposite = new Composite(content, SWT.NONE);
    171        helpComposite.setLayout(new GridLayout(1, true));
    172        helpComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    173
    174        label = new Label(helpComposite, SWT.LEFT);
    175        label.setFont(curFont);
    176        label.setText("Type of Link: ");
    177
    178        Button helpButton = new Button(helpComposite, SWT.PUSH);
    179        helpButton.setImage(ViewProperties.getHelpIcon());
    180        helpButton.setToolTipText("Help on Links");
    181        helpButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    182        helpButton.addSelectionListener(new SelectionAdapter() {
    183            @Override
    184            public void widgetSelected(SelectionEvent e) {
    185                final String msg = "The Type of Link specifies which type of link the user wants to create. \n"
    186                        + "It could be hard, soft or external links. \n\n"
    187                        + "Hard Link: \n"
    188                        + "Hard Link creates a hard link to a pre-existing object in an HDF5 file. \n"
    189                        + "The target object must already exist in the file.\n"
    190                        + "The HDF5 library keeps a count of all hard links pointing to an object. \n\n"
    191                        + "Soft Link: \n"
    192                        + "Soft Link creates a new soft link to an object in an HDF5 file. \n"
    193                        + "Soft links are only for use only if the target object is in the current file. \n"
    194                        + "Unlike hard links, a soft link in an HDF5 file is allowed to dangle, \n"
    195                        + "meaning that the target object need not exist at the time that the link is created.\n"
    196                        + "The HDF5 library does not keep a count of soft links.  \n\n"
    197                        + "External Link: \n"
    198                        + "External Link creates a new soft link to an external object, which is an \n"
    199                        + "object in a different HDF5 file from the location of the link. \n"
    200                        + "External links are allowed to dangle like soft links. \n\n"
    201                        + "Soft links and external links are also known as symbolic links as they use "
    202                        + "a name to point to an object; hard links employ an object's address in the file.  \n\n\n";
    203
    204                Tools.showInformation(shell, "Help", msg);
    205            }
    206        });
    207
    208        Composite typeComposite = new Composite(content, SWT.BORDER);
    209        typeComposite.setLayout(new GridLayout(3, true));
    210        typeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    211
    212        hardLink = new Button(typeComposite, SWT.RADIO);
    213        hardLink.setFont(curFont);
    214        hardLink.setText("Hard Link");
    215        hardLink.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
    216        hardLink.addSelectionListener(new SelectionAdapter() {
    217            @Override
    218            public void widgetSelected(SelectionEvent e) {
    219                targetFile.setEnabled(false);
    220                targetFileButton.setEnabled(false);
    221                targetObject.setEnabled(true);
    222                targetObject.setEditable(false);
    223                targetObject.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
    224
    225                targetObject.removeAll();
    226                retrieveObjects(fileFormat);
    227
    228                targetObject.select(0);
    229            }
    230        });
    231
    232        softLink = new Button(typeComposite, SWT.RADIO);
    233        softLink.setFont(curFont);
    234        softLink.setText("Soft Link");
    235        softLink.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
    236        softLink.addSelectionListener(new SelectionAdapter() {
    237            @Override
    238            public void widgetSelected(SelectionEvent e) {
    239                targetFile.setEnabled(false);
    240                targetFileButton.setEnabled(false);
    241                targetObject.setEnabled(true);
    242                targetObject.setEditable(true);
    243                targetObject.setBackground(null);
    244
    245                targetObject.removeAll();
    246                retrieveObjects(fileFormat);
    247
    248                targetObject.select(0);
    249            }
    250        });
    251
    252        externalLink = new Button(typeComposite, SWT.RADIO);
    253        externalLink.setFont(curFont);
    254        externalLink.setText("External Link");
    255        externalLink.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false));
    256        externalLink.addSelectionListener(new SelectionAdapter() {
    257            @Override
    258            public void widgetSelected(SelectionEvent e) {
    259                targetFile.setEnabled(true);
    260                targetFileButton.setEnabled(true);
    261                targetObject.setEnabled(true);
    262                targetObject.setEditable(true);
    263                targetObject.setBackground(null);
    264                targetObject.removeAll();
    265            }
    266        });
    267
    268        label = new Label(content, SWT.LEFT);
    269        label.setFont(curFont);
    270        label.setText("Target File: ");
    271
    272        Composite fileComposite = new Composite(content, SWT.NONE);
    273        GridLayout layout = new GridLayout(2, false);
    274        layout.horizontalSpacing = 0;
    275        layout.marginHeight = 0;
    276        layout.marginWidth = 0;
    277        fileComposite.setLayout(layout);
    278        fileComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    279
    280        targetFile = new Text(fileComposite, SWT.SINGLE | SWT.BORDER);
    281        targetFile.setFont(curFont);
    282        targetFile.setEnabled(false);
    283        targetFile.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    284        targetFile.addTraverseListener(new TraverseListener() {
    285            @Override
    286            public void keyTraversed(TraverseEvent e) {
    287                if (e.detail == SWT.TRAVERSE_RETURN) {
    288                    String filename = targetFile.getText();
    289
    290                    if (filename == null || filename.length() <= 0) return;
    291
    292                    File chosenFile = new File(filename);
    293
    294                    if (!chosenFile.exists()) {
    295                        return;
    296                    }
    297
    298                    if (chosenFile.isDirectory()) {
    299                        currentDir = chosenFile.getPath();
    300                    }
    301                    else {
    302                        currentDir = chosenFile.getParent();
    303                    }
    304
    305                    //Check if the target File is not the current file.
    306                    String currentFileName = fileFormat.getAbsolutePath();
    307                    if(currentFileName.equals(chosenFile.getAbsolutePath())) {
    308                        Tools.showError(shell, "Traverse",
    309                                "Please select a file other than the current file for external links.");
    310                        targetFile.setText("");
    311                        return;
    312                    }
    313
    314                    getTargetFileObjs();
    315
    316                    if(targetObject.getItemCount() > 0) targetObject.select(0);
    317                }
    318            }
    319        });
    320
    321        targetFileButton = new Button(fileComposite, SWT.PUSH);
    322        targetFileButton.setFont(curFont);
    323        targetFileButton.setText("Browse...");
    324        targetFileButton.setEnabled(false);
    325        targetFileButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
    326        targetFileButton.addSelectionListener(new SelectionAdapter() {
    327            @Override
    328            public void widgetSelected(SelectionEvent e) {
    329                String filename = null;
    330                filename = openTargetFile();
    331
    332                if (filename == null) {
    333                    return;
    334                }
    335
    336                targetFile.setText(filename);
    337                getTargetFileObjs();
    338
    339                if(targetObject.getItemCount() > 0) targetObject.select(0);
    340            }
    341        });
    342
    343        label = new Label(content, SWT.LEFT);
    344        label.setFont(curFont);
    345        label.setText("Target Object: ");
    346
    347        targetObject = new CCombo(content, SWT.DROP_DOWN | SWT.BORDER);
    348        targetObject.setFont(curFont);
    349        targetObject.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    350        targetObject.setEditable(false);
    351        targetObject.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
    352
    353        groupList = new ArrayList<>(objList.size());
    354        Object obj = null;
    355        Iterator<?> iterator = objList.iterator();
    356        String fullName = null;
    357        int idx_root = -1, idx = -1;
    358        while (iterator.hasNext()) {
    359            obj = iterator.next();
    360            idx++;
    361
    362            if (obj instanceof Group) {
    363                Group g = (Group) obj;
    364                groupList.add(g);
    365                if (g.isRoot()) {
    366                    fullName = HObject.SEPARATOR;
    367                    idx_root = idx;
    368                }
    369                else {
    370                    fullName = g.getPath() + g.getName() + HObject.SEPARATOR;
    371                }
    372                parentChoice.add(fullName);
    373            }
    374            else {
    375                fullName = ((HObject) obj).getPath() + ((HObject) obj).getName();
    376            }
    377
    378            targetObject.add(fullName);
    379        }
    380
    381        targetObject.remove(idx_root);
    382        objList.remove(idx_root);
    383
    384        if (parentGroup.isRoot()) {
    385            parentChoice.select(parentChoice.indexOf(HObject.SEPARATOR));
    386        }
    387        else {
    388            parentChoice.select(parentChoice.indexOf(parentGroup.getPath() + parentGroup.getName()
    389                    + HObject.SEPARATOR));
    390        }
    391
    392        // Dummy label to take up space as dialog is resized
    393        label = new Label(content, SWT.LEFT);
    394        label.setFont(curFont);
    395        label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    396
    397
    398        // Create the Ok/Cancel button region
    399        Composite buttonComposite = new Composite(shell, SWT.NONE);
    400        buttonComposite.setLayout(new GridLayout(2, true));
    401        buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    402
    403        Button okButton = new Button(buttonComposite, SWT.PUSH);
    404        okButton.setFont(curFont);
    405        okButton.setText("   &OK   ");
    406        okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false));
    407        okButton.addSelectionListener(new SelectionAdapter() {
    408            @Override
    409            public void widgetSelected(SelectionEvent e) {
    410                newObject = createLink();
    411
    412                if (newObject != null) {
    413                    shell.dispose();
    414                }
    415            }
    416        });
    417
    418        Button cancelButton = new Button(buttonComposite, SWT.PUSH);
    419        cancelButton.setFont(curFont);
    420        cancelButton.setText(" &Cancel ");
    421        cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false));
    422        cancelButton.addSelectionListener(new SelectionAdapter() {
    423            @Override
    424            public void widgetSelected(SelectionEvent e) {
    425                newObject = null;
    426                shell.dispose();
    427                ((Vector<Group>) groupList).setSize(0);
    428            }
    429        });
    430
    431        hardLink.setSelection(true);
    432        targetObject.select(0);
    433
    434        shell.pack();
    435
    436        shell.addDisposeListener(new DisposeListener() {
    437            @Override
    438            public void widgetDisposed(DisposeEvent e) {
    439                if (curFont != null) curFont.dispose();
    440            }
    441        });
    442
    443        shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT));
    444
    445        Rectangle parentBounds = parent.getBounds();
    446        Point shellSize = shell.getSize();
    447        shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2),
    448                          (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2));
    449
    450        shell.open();
    451
    452        Display display = shell.getDisplay();
    453        while (!shell.isDisposed())
    454            if (!display.readAndDispatch())
    455                display.sleep();
    456    }
    457
    458    private HObject createLink() {
    459        String name = null;
    460        Group pgroup = null;
    461        HObject obj = null;
    462
    463        name = nameField.getText().trim();
    464        if ((name == null) || (name.length() < 1)) {
    465            shell.getDisplay().beep();
    466            Tools.showError(shell, "Create", "Link name is not specified.");
    467            return null;
    468        }
    469
    470        if (name.indexOf(HObject.SEPARATOR) >= 0) {
    471            shell.getDisplay().beep();
    472            Tools.showError(shell, "Create", "Link name cannot contain path.");
    473            return null;
    474        }
    475
    476        pgroup = groupList.get(parentChoice.getSelectionIndex());
    477
    478        if (pgroup == null) {
    479            shell.getDisplay().beep();
    480            Tools.showError(shell, "Create", "Parent group is null.");
    481            return null;
    482        }
    483
    484        if (hardLink.getSelection()) {
    485            HObject targetObj = (HObject) objList.get(targetObject
    486                    .getSelectionIndex());
    487
    488            if (targetObj == null) {
    489                shell.getDisplay().beep();
    490                Tools.showError(shell, "Create", "Target object is null.");
    491                return null;
    492            }
    493
    494            if ((targetObj instanceof Group) && ((Group) targetObj).isRoot()) {
    495                shell.getDisplay().beep();
    496                Tools.showError(shell, "Create", "Cannot make a link to the root group.");
    497                return null;
    498            }
    499
    500            try {
    501                obj = fileFormat.createLink(pgroup, name, targetObj);
    502            }
    503            catch (Exception ex) {
    504                shell.getDisplay().beep();
    505                Tools.showError(shell, "Create", ex.getMessage());
    506                return null;
    507            }
    508        }
    509        else if (softLink.getSelection()){
    510            String target_name = targetObject.getText();
    511            if (target_name.length() < 1)  {
    512                shell.getDisplay().beep();
    513                Tools.showError(shell, "Create", "Target object name is not specified.");
    514                return null;
    515            }
    516
    517            /*
    518             * While checking for the existence of the object that the soft link points to,
    519             * the following function currently just calls H5Oopen, which will fail and
    520             * throw an HDF5 error stack for dangling soft links. Due to this, we
    521             * temporarily suppress the HDF5 error stack.
    522             */
    523            HObject targetObj = null;
    524            try {
    525                H5.H5error_off();
    526                targetObj = fileFormat.get(target_name);
    527            }
    528            catch (Exception ex) {
    529                /* It is possible that this is a soft link to a non-existent
    530                 * object, in which case this exception would be normal.
    531                 * For this reason, no logging is done here even though there
    532                 * is the possibility of a real HDF5 exception being thrown
    533                 * if something went terribly wrong.
    534                 */
    535            }
    536            finally {
    537                H5.H5error_on();
    538            }
    539
    540            String tObj = null;
    541            if (targetObj == null) {
    542                tObj = target_name;
    543
    544                if (!tObj.startsWith(HObject.SEPARATOR)) {
    545                    tObj = HObject.SEPARATOR + tObj;
    546                }
    547            }
    548
    549            if ((targetObj instanceof Group) && ((Group) targetObj).isRoot()) {
    550                shell.getDisplay().beep();
    551                Tools.showError(shell, "Create", "Cannot make a link to the root group.");
    552                return null;
    553            }
    554
    555            try {
    556                if (targetObj != null)
    557                    obj = fileFormat.createLink(pgroup, name, targetObj, Group.LINK_TYPE_SOFT);
    558                else if (tObj != null)
    559                    obj = fileFormat.createLink(pgroup, name, tObj, Group.LINK_TYPE_SOFT);
    560            }
    561            catch (Exception ex) {
    562                ex.printStackTrace();
    563                shell.getDisplay().beep();
    564                Tools.showError(shell, "Create", ex.getMessage());
    565                return null;
    566            }
    567        }
    568        else if (externalLink.getSelection()){
    569            String TargetFileName = targetFile.getText();
    570            FileFormat TargetFileFormat = null;
    571            int fileAccessID = FileFormat.FILE_CREATE_OPEN;
    572
    573            File TargetFile = new File(TargetFileName);
    574
    575            if (!TargetFile.exists()) {
    576                return null;
    577            }
    578            FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
    579            try {
    580                TargetFileFormat = h5format.createInstance(TargetFileName, fileAccessID);
    581                TargetFileFormat.open(); //open the file
    582            }
    583            catch (Exception ex) {
    584                log.debug("external link:", ex);
    585                return null;
    586            }
    587
    588            HObject targetObj = null;
    589            try{
    590                targetObj = TargetFileFormat.get(targetObject.getText());
    591            }
    592            catch (Exception ex) {
    593                ex.printStackTrace();
    594            }
    595
    596            try {
    597                TargetFileFormat.close();
    598            }
    599            catch (Exception ex) {
    600                log.debug("external link:", ex);
    601            }
    602
    603            String tFileObj = null;
    604            if(targetObj==null){
    605                String tObj = null;
    606                tObj = targetObject.getText();
    607                if (tObj.length() < 1)  {
    608                    shell.getDisplay().beep();
    609                    Tools.showError(shell, "Create", "Target object name not specified.");
    610                    return null;
    611                }
    612                tFileObj = TargetFileName + FileFormat.FILE_OBJ_SEP + tObj;
    613            }
    614
    615            try {
    616                if(targetObj !=null)
    617                    obj = fileFormat.createLink(pgroup, name, targetObj, Group.LINK_TYPE_EXTERNAL);
    618                else if(tFileObj!=null)
    619                    obj = fileFormat.createLink(pgroup, name, tFileObj, Group.LINK_TYPE_EXTERNAL);
    620            }
    621            catch (Exception ex) {
    622                ex.printStackTrace();
    623                shell.getDisplay().beep();
    624                Tools.showError(shell, "Create", ex.getMessage());
    625                return null;
    626            }
    627        }
    628
    629        return obj;
    630    }
    631
    632    private String openTargetFile() {
    633        FileDialog fchooser = new FileDialog(shell, SWT.OPEN);
    634        fchooser.setFilterPath(currentDir);
    635
    636        DefaultFileFilter filter = DefaultFileFilter.getFileFilter();
    637        fchooser.setFilterExtensions(new String[] {"*", filter.getExtensions()});
    638        fchooser.setFilterNames(new String[] {"All Files", filter.getDescription()});
    639        fchooser.setFilterIndex(1);
    640
    641        if(fchooser.open() == null) return null;
    642
    643        File chosenFile = new File(fchooser.getFilterPath() + File.separator + fchooser.getFileName());
    644
    645        if (!chosenFile.exists()) {
    646            return null;
    647        }
    648
    649        if (chosenFile.isDirectory()) {
    650            currentDir = chosenFile.getPath();
    651        }
    652        else {
    653            currentDir = chosenFile.getParent();
    654        }
    655
    656        //Check if the target File is not the current file.
    657        String currentFileName = fileFormat.getAbsolutePath();
    658        if(currentFileName.equals(chosenFile.getAbsolutePath())) {
    659            Tools.showError(shell, "Open", "Please select a file other than the current file for external links.");
    660            targetFile.setText("");
    661            return null;
    662        }
    663
    664        return chosenFile.getAbsolutePath();
    665    }
    666
    667    //Function to check if the target File is open in TreeView
    668    private boolean isFileOpen(String filename)
    669    {
    670        boolean isOpen = false;
    671        FileFormat theFile = null;
    672
    673        Iterator<?> iterator = fileList.iterator();
    674        while(iterator.hasNext()) {
    675            theFile = (FileFormat)iterator.next();
    676            if (theFile.getFilePath().equals(filename)) {
    677                isOpen = true;
    678                if(!theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))){
    679                    targetObject.setEnabled(false);
    680                }
    681                retrieveObjects(theFile);
    682                break;
    683            }
    684        }
    685
    686        return isOpen;
    687    }
    688
    689    private List<HObject> getAllUserObjectsBreadthFirst(FileFormat file) {
    690        if (file == null) return null;
    691
    692        ArrayList<HObject> breadthFirstObjects = new ArrayList<>();
    693        Queue<HObject> currentChildren = new LinkedList<>();
    694        HObject currentObject = file.getRootObject();
    695
    696        if (currentObject == null) {
    697            log.debug("getAllUserObjectsBreadthFirst(): file root object is null");
    698            return null;
    699        }
    700
    701        breadthFirstObjects.add(file.getRootObject()); // Add the root object to the list first
    702
    703        // Add all root object children to a Queue
    704        currentChildren.addAll(((Group) currentObject).getMemberList());
    705
    706        while(!currentChildren.isEmpty()) {
    707            currentObject = currentChildren.remove();
    708            breadthFirstObjects.add(currentObject);
    709
    710            if(currentObject instanceof Group) {
    711                if(((Group) currentObject).getNumberOfMembersInFile() <= 0) continue;
    712
    713                currentChildren.addAll(((Group) currentObject).getMemberList());
    714            }
    715        }
    716
    717        return breadthFirstObjects;
    718    }
    719
    720    // Retrieves the list of objects from the file
    721    private void retrieveObjects(FileFormat file) {
    722        HObject obj = null;
    723        List<HObject> userObjectList = getAllUserObjectsBreadthFirst(file);
    724        Iterator<HObject> iterator;
    725        String fullName = null;
    726
    727        if (userObjectList == null) {
    728            log.debug("retrieveObjects(): user object list is null");
    729            return;
    730        }
    731
    732        iterator = userObjectList.iterator();
    733        while (iterator.hasNext()) {
    734            obj = iterator.next();
    735
    736            if (obj instanceof Group) {
    737                Group g = (Group) obj;
    738                if (g.isRoot()) {
    739                    fullName = HObject.SEPARATOR;
    740                }
    741                else {
    742                    fullName = g.getPath() + g.getName() + HObject.SEPARATOR;
    743                }
    744            }
    745            else {
    746                fullName = obj.getPath() + obj.getName();
    747            }
    748
    749            targetObject.add(fullName);
    750        }
    751
    752        // Remove the root group "/" from the target objects
    753        targetObject.remove(0);
    754    }
    755
    756    // Retrieves objects from Target File.
    757    private void getTargetFileObjs(){
    758        FileFormat fileFormatC = null;
    759        int fileAccessID = FileFormat.FILE_CREATE_OPEN;
    760        String filename = null;
    761        filename = targetFile.getText();
    762
    763        if (filename == null || filename.length()<1) {
    764            return;
    765        }
    766
    767        // Check if the target File is open in treeView
    768        if (isFileOpen(filename)) {
    769            return;
    770        }
    771
    772        File chosenFile = new File(filename);
    773
    774        if (!chosenFile.exists()) {
    775            targetObject.setEnabled(false);
    776            return;
    777        }
    778
    779        FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5);
    780        try {
    781            fileFormatC = h5format.createInstance(filename, fileAccessID);
    782            fileFormatC.open(); //open the file
    783        }
    784        catch (Exception ex) {
    785            shell.getDisplay().beep();
    786            Tools.showError(shell, "Target", "Invalid File Format");
    787            targetFile.setText("");
    788            return;
    789        }
    790
    791        // get the list of objects from the file
    792        retrieveObjects(fileFormatC);
    793
    794        try {
    795            fileFormatC.close();
    796        }
    797        catch (Exception ex) {
    798            log.debug("FileFormat close:", ex);
    799        }
    800    }
    801
    802    /** @return the new dataset created. */
    803    public HObject getObject() {
    804        return newObject;
    805    }
    806
    807    /** @return the parent group of the new dataset. */
    808    public Group getParentGroup() {
    809        return parentGroup;
    810    }
    811}