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