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.Dimension; 019import java.awt.GridLayout; 020import java.awt.Insets; 021import java.awt.Point; 022import java.awt.Toolkit; 023import java.awt.event.ActionEvent; 024import java.awt.event.ActionListener; 025import java.awt.event.ItemEvent; 026import java.awt.event.ItemListener; 027import java.awt.event.KeyEvent; 028import java.io.File; 029import java.util.Enumeration; 030import java.util.Iterator; 031import java.util.List; 032import java.util.Vector; 033 034import javax.swing.BorderFactory; 035import javax.swing.ButtonGroup; 036import javax.swing.JButton; 037import javax.swing.JCheckBox; 038import javax.swing.JComboBox; 039import javax.swing.JDialog; 040import javax.swing.JFileChooser; 041import javax.swing.JFrame; 042import javax.swing.JLabel; 043import javax.swing.JOptionPane; 044import javax.swing.JPanel; 045import javax.swing.JRadioButton; 046import javax.swing.JTextField; 047import javax.swing.border.TitledBorder; 048import javax.swing.event.DocumentEvent; 049import javax.swing.event.DocumentListener; 050import javax.swing.tree.DefaultMutableTreeNode; 051import javax.swing.tree.TreeNode; 052 053import hdf.object.DataFormat; 054import hdf.object.FileFormat; 055import hdf.object.Group; 056import hdf.object.HObject; 057 058/** 059 * NewLinkDialog shows a message dialog requesting user input for creating a 060 * new links. 061 * 062 * @author Peter X. Cao 063 * @version 2.4 9/6/2007 064 */ 065public class NewLinkDialog extends JDialog implements ActionListener,DocumentListener, ItemListener { 066 private static final long serialVersionUID = 7100424106041533918L; 067 068 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewLinkDialog.class); 069 070 private JTextField nameField; 071 072 @SuppressWarnings("rawtypes") 073 private JComboBox parentChoice, targetObject; 074 075 private String currentDir; 076 077 private JTextField targetFile; 078 079 private JButton targetFileButton; 080 081 private JRadioButton hardLink, softLink, externalLink; 082 083 private JCheckBox checkUnsigned; 084 085 /** a list of current groups */ 086 private List<HObject> groupList; 087 088 /** a list of current objects */ 089 private List<?> objList; 090 091 private HObject newObject; 092 093 private FileFormat fileFormat; 094 095 private final Toolkit toolkit; 096 097 private ViewManager viewer; 098 099 private final List<?> fileList; 100 101 102 /** 103 * Constructs NewLinkDialog with specified list of possible parent groups. 104 * 105 * @param owner 106 * the owner of the input 107 * @param pGroup 108 * the parent group which the new group is added to. 109 * @param objs 110 * the list of all objects. 111 */ 112 @SuppressWarnings({ "rawtypes", "unchecked" }) 113 public NewLinkDialog(JFrame owner, Group pGroup, List<?> objs) { 114 super(owner, "New Link...", true); 115 116 viewer = (ViewManager)owner; 117 fileList = viewer.getTreeView().getCurrentFiles(); 118 119 newObject = null; 120 fileFormat = pGroup.getFileFormat(); 121 toolkit = Toolkit.getDefaultToolkit(); 122 objList = objs; 123 124 currentDir = ViewProperties.getWorkDir(); 125 126 parentChoice = new JComboBox(); 127 parentChoice.setName("linkparent"); 128 targetObject = new JComboBox(); 129 targetObject.setEditable(false); 130 131 groupList = new Vector<HObject>(objs.size()); 132 HObject obj = null; 133 Iterator<?> iterator = objs.iterator(); 134 String full_name = null; 135 int idx_root = -1, idx = -1; 136 while (iterator.hasNext()) { 137 obj = (HObject) iterator.next(); 138 idx++; 139 140 if (obj instanceof Group) { 141 Group g = (Group) obj; 142 groupList.add(obj); 143 if (g.isRoot()) { 144 full_name = HObject.separator; 145 idx_root = idx; 146 } 147 else { 148 full_name = g.getPath() + g.getName() + HObject.separator; 149 } 150 parentChoice.addItem(full_name); 151 } 152 else { 153 full_name = obj.getPath() + obj.getName(); 154 } 155 156 targetObject.addItem(full_name); 157 } 158 159 targetObject.removeItemAt(idx_root); 160 objList.remove(idx_root); 161 162 if (pGroup.isRoot()) { 163 parentChoice.setSelectedItem(HObject.separator); 164 } 165 else { 166 parentChoice.setSelectedItem(pGroup.getPath() + pGroup.getName() 167 + HObject.separator); 168 } 169 170 171 JPanel contentPane = (JPanel) getContentPane(); 172 contentPane.setLayout(new BorderLayout(5, 5)); 173 contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5)); 174 int w = 600 + (ViewProperties.getFontSize() - 12) * 15; 175 int h = 280 + (ViewProperties.getFontSize() - 12) * 10; 176 contentPane.setPreferredSize(new Dimension(w, h)); 177 178 JButton okButton = new JButton(" Ok "); 179 okButton.setActionCommand("Ok"); 180 okButton.setName("makelink"); 181 okButton.setMnemonic(KeyEvent.VK_O); 182 okButton.addActionListener(this); 183 184 JButton cancelButton = new JButton("Cancel"); 185 cancelButton.setMnemonic(KeyEvent.VK_C); 186 cancelButton.setActionCommand("Cancel"); 187 cancelButton.addActionListener(this); 188 189 // set OK and CANCEL buttons 190 JPanel buttonPanel = new JPanel(); 191 buttonPanel.add(okButton); 192 buttonPanel.add(cancelButton); 193 contentPane.add(buttonPanel, BorderLayout.SOUTH); 194 195 // set NAME and PARENT GROUP panel 196 JPanel namePanel = new JPanel(); 197 namePanel.setLayout(new BorderLayout(5, 5)); 198 JPanel tmpP = new JPanel(); 199 tmpP.setLayout(new GridLayout(5, 1,5, 5)); 200 tmpP.add(new JLabel("Link name: ")); 201 tmpP.add(new JLabel("Parent group: ")); 202 203 JPanel tmpLinkJPanel = new JPanel(); 204 tmpLinkJPanel.setLayout(new GridLayout(2, 1)); 205 tmpLinkJPanel.add(new JLabel("Type of Link: ")); 206 JButton helpButton = new JButton(ViewProperties.getHelpIcon()); 207 helpButton.setToolTipText("Help on Links"); 208 helpButton.setMargin(new Insets(0, 0, 0, 0)); 209 helpButton.addActionListener(this); 210 helpButton.setActionCommand("Help on Links"); 211 tmpLinkJPanel.add(helpButton); 212 tmpP.add(tmpLinkJPanel); 213 tmpP.add(new JLabel("Target File: ")); 214 tmpP.add(new JLabel("Target Object: ")); 215 namePanel.add(tmpP, BorderLayout.WEST); 216 217 tmpP = new JPanel(); 218 tmpP.setLayout(new GridLayout(5, 1,5,5)); 219 nameField = new JTextField(); 220 nameField.setName("linkname"); 221 tmpP.add(nameField); 222 tmpP.add(parentChoice); 223 224 JPanel tmpP0 = new JPanel(); 225 tmpP0.setLayout(new GridLayout(1, 3)); 226 tmpP0.add(hardLink = new JRadioButton("Hard Link ", true)); 227 tmpP0.add(softLink = new JRadioButton("Soft Link ")); 228 tmpP0.add(externalLink = new JRadioButton("External Link ")); 229 tmpP0.setBorder(new TitledBorder("")); 230 tmpP.add(tmpP0); 231 ButtonGroup bgroup = new ButtonGroup(); 232 bgroup.add(hardLink); 233 bgroup.add(softLink); 234 bgroup.add(externalLink); 235 hardLink.addItemListener(this); 236 hardLink.setName("hardlink"); 237 softLink.addItemListener(this); 238 softLink.setName("softlink"); 239 externalLink.addItemListener(this); 240 externalLink.setName("externallink"); 241 242 JPanel p0 = new JPanel(); 243 p0.setLayout(new BorderLayout()); 244 p0.add(targetFile = new JTextField(), BorderLayout.CENTER); 245 targetFile.getDocument().addDocumentListener(this); 246 targetFile.addActionListener(this); 247 targetFile.setActionCommand("Link to File"); 248 JButton b = new JButton("Browse..."); 249 targetFileButton = b; 250 b.setActionCommand("Browse File"); 251 b.setName("targetfilebutton"); 252 b.addActionListener(this); 253 p0.add(b, BorderLayout.EAST); 254 tmpP.add(p0); 255 targetFile.setEnabled(false); 256 targetFileButton.setEnabled(false); 257 258 tmpP.add(targetObject); 259 targetObject.setName("linktarget"); 260 namePanel.add(tmpP, BorderLayout.CENTER); 261 contentPane.add(namePanel, BorderLayout.CENTER); 262 263 // locate the H5Property dialog 264 Point l = owner.getLocation(); 265 l.x += 250; 266 l.y += 100; 267 setLocation(l); 268 validate(); 269 pack(); 270 } 271 272 public void actionPerformed(ActionEvent e) { 273 Object source = e.getSource(); 274 String cmd = e.getActionCommand(); 275 276 if (cmd.equals("Help on Links")) { 277 final String msg = "The Type of Link specifies which type of link the user wants to create. \n" 278 + "It could be hard, soft or external links. \n\n" 279 + "<html><b>Hard Link</b></html> \n" 280 + "Hard Link creates a hard link to a pre-existing object in an HDF5 file. \n" 281 + "The target object must already exist in the file.\n" 282 + "The HDF5 library keeps a count of all hard links pointing to an object. \n\n" 283 + "<html><b>Soft Link</b></html> \n" 284 + "Soft Link creates a new soft link to an object in an HDF5 file. \n" 285 + "Soft links are only for use only if the target object is in the current file. \n" 286 + "Unlike hard links, a soft link in an HDF5 file is allowed to dangle, \n" 287 + "meaning that the target object need not exist at the time that the link is created.\n" 288 + "The HDF5 library does not keep a count of soft links \n\n" 289 + "<html><b>External Link</b></html> \n" 290 + "External Link creates a new soft link to an external object, which is an object\n" 291 + "in a different HDF5 file from the location of the link. External links are \n" 292 + "allowed to dangle like soft links. \n\n" 293 + "Soft links and external links are also known as symbolic links as they use \n" 294 + "a name to point to an object; hard links employ an object's address in the file. \n\n\n"; 295 JOptionPane.showMessageDialog(this, msg); 296 } 297 298 if (cmd.equals("Browse File")) { 299 String filename = null; 300 filename = openTargetFile(); 301 302 if (filename == null) { 303 return; 304 } 305 targetFile.setText(filename); 306 } 307 308 if (cmd.equals("Ok")) { 309 newObject = createLink(); 310 311 if (newObject != null) { 312 dispose(); 313 } 314 } 315 if (cmd.equals("Cancel")) { 316 newObject = null; 317 dispose(); 318 ((Vector<HObject>) groupList).setSize(0); 319 } 320 } 321 322 private String openTargetFile() 323 { 324 JFileChooser fchooser = new JFileChooser(currentDir); 325 fchooser.setFileFilter(DefaultFileFilter.getFileFilter()); 326 327 int returnVal = fchooser.showOpenDialog(this); 328 if(returnVal != JFileChooser.APPROVE_OPTION) { 329 return null; 330 } 331 332 File choosedFile = fchooser.getSelectedFile(); 333 334 if (choosedFile == null) { 335 return null; 336 } 337 338 if (choosedFile.isDirectory()) { 339 currentDir = choosedFile.getPath(); 340 } 341 else { 342 currentDir = choosedFile.getParent(); 343 } 344 345 return choosedFile.getAbsolutePath(); 346 } 347 348 private final List<Object> breadthFirstUserObjects(TreeNode node) 349 { 350 if (node == null) { 351 return null; 352 } 353 354 Vector<Object> list = new Vector<Object>(); 355 DefaultMutableTreeNode theNode = null; 356 Enumeration<?> local_enum = ((DefaultMutableTreeNode)node).breadthFirstEnumeration(); 357 while(local_enum.hasMoreElements()) { 358 theNode = (DefaultMutableTreeNode)local_enum.nextElement(); 359 list.add(theNode.getUserObject()); 360 } 361 362 return list; 363 } 364 365 private HObject createLink() { 366 String name = null; 367 Group pgroup = null; 368 HObject obj = null; 369 370 name = nameField.getText().trim(); 371 if ((name == null) || (name.length() < 1)) { 372 toolkit.beep(); 373 JOptionPane.showMessageDialog(this, 374 "Link name is not specified.", getTitle(), 375 JOptionPane.ERROR_MESSAGE); 376 return null; 377 } 378 379 if (name.indexOf(HObject.separator) >= 0) { 380 toolkit.beep(); 381 JOptionPane.showMessageDialog(this, 382 "Link name cannot contain path.", getTitle(), 383 JOptionPane.ERROR_MESSAGE); 384 return null; 385 } 386 387 pgroup = (Group) groupList.get(parentChoice.getSelectedIndex()); 388 389 if (pgroup == null) { 390 toolkit.beep(); 391 JOptionPane.showMessageDialog(this, "Parent group is null.", 392 getTitle(), JOptionPane.ERROR_MESSAGE); 393 return null; 394 } 395 396 if (hardLink.isSelected()) { 397 HObject targetObj = (HObject) objList.get(targetObject 398 .getSelectedIndex()); 399 400 if (targetObj == null) { 401 toolkit.beep(); 402 JOptionPane.showMessageDialog(this, "Target object is null.", 403 getTitle(), JOptionPane.ERROR_MESSAGE); 404 return null; 405 } 406 407 if ((targetObj instanceof Group) && ((Group) targetObj).isRoot()) { 408 toolkit.beep(); 409 JOptionPane.showMessageDialog(this, 410 "Cannot make a link to the root group.", getTitle(), 411 JOptionPane.ERROR_MESSAGE); 412 return null; 413 } 414 415 try { 416 obj = fileFormat.createLink(pgroup, name, targetObj); 417 } 418 catch (Exception ex) { 419 toolkit.beep(); 420 JOptionPane.showMessageDialog(this, ex, getTitle(), 421 JOptionPane.ERROR_MESSAGE); 422 return null; 423 } 424 } 425 else if (softLink.isSelected()){ 426 String target_name = targetObject.getEditor().getItem().toString(); 427 if (target_name.length() < 1) { 428 toolkit.beep(); 429 JOptionPane.showMessageDialog(this, 430 "Target object name is not specified.", getTitle(), 431 JOptionPane.ERROR_MESSAGE); 432 return null; 433 } 434 435 HObject targetObj = null; 436 try { 437 targetObj = fileFormat.get(targetObject.getEditor().getItem().toString()); 438 } 439 catch (Exception ex) { 440 log.debug("softlink:", ex); 441 } 442 443 String tObj = null; 444 if(targetObj==null){ 445 tObj = targetObject.getEditor().getItem().toString(); 446 447 if (!tObj.startsWith(HObject.separator)) { 448 tObj = HObject.separator + tObj; 449 } 450 } 451 452 if ((targetObj instanceof Group) && ((Group) targetObj).isRoot()) { 453 toolkit.beep(); 454 JOptionPane.showMessageDialog(this, 455 "Cannot make a link to the root group.", getTitle(), 456 JOptionPane.ERROR_MESSAGE); 457 return null; 458 } 459 460 try { 461 if(targetObj !=null) 462 obj = fileFormat.createLink(pgroup, name, targetObj, Group.LINK_TYPE_SOFT); 463 else if(tObj!=null) 464 obj = fileFormat.createLink(pgroup, name, tObj, Group.LINK_TYPE_SOFT); 465 } 466 catch (Exception ex) { 467 ex.printStackTrace(); 468 toolkit.beep(); 469 JOptionPane.showMessageDialog(this, ex, getTitle(), 470 JOptionPane.ERROR_MESSAGE); 471 return null; 472 } 473 } 474 else if (externalLink.isSelected()){ 475 String TargetFileName = targetFile.getText(); 476 FileFormat TargetFileFormat = null; 477 int fileAccessID = FileFormat.FILE_CREATE_OPEN; 478 479 File TargetFile = new File(TargetFileName); 480 481 if (!TargetFile.exists()) { 482 return null; 483 } 484 FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5); 485 try { 486 //h5format.close(); 487 TargetFileFormat = h5format.createInstance(TargetFileName, fileAccessID); 488 TargetFileFormat.open(); //open the file 489 } 490 catch (Exception ex) { 491 log.debug("external link:", ex); 492 return null; 493 } 494 495 HObject targetObj = null; 496 try{ 497 targetObj = TargetFileFormat.get(targetObject.getEditor().getItem().toString()); 498 } 499 catch (Exception ex) { 500 ex.printStackTrace(); 501 } 502 503 try { 504 TargetFileFormat.close(); 505 } 506 catch (Exception ex) { 507 log.debug("external link:", ex); 508 } 509 510 String tFileObj = null; 511 if(targetObj==null){ 512 String tObj = null; 513 tObj = targetObject.getEditor().getItem().toString(); 514 if (tObj.length() < 1) { 515 toolkit.beep(); 516 JOptionPane.showMessageDialog(this, 517 "Target object name not specified.", getTitle(), 518 JOptionPane.ERROR_MESSAGE); 519 return null; 520 } 521 tFileObj = TargetFileName + FileFormat.FILE_OBJ_SEP + tObj; 522 } 523// should allow to link to the root of an external file 524// if ((targetObj instanceof Group) && ((Group) targetObj).isRoot()) { 525// toolkit.beep(); 526// JOptionPane.showMessageDialog(this, 527// "Cannot make a link to the root group.", getTitle(), 528// JOptionPane.ERROR_MESSAGE); 529// return null; 530// } 531 532 try { 533 if(targetObj !=null) 534 obj = fileFormat.createLink(pgroup, name, targetObj, Group.LINK_TYPE_EXTERNAL); 535 else if(tFileObj!=null) 536 obj = fileFormat.createLink(pgroup, name, tFileObj, Group.LINK_TYPE_EXTERNAL); 537 } 538 catch (Exception ex) { 539 ex.printStackTrace(); 540 toolkit.beep(); 541 JOptionPane.showMessageDialog(this, ex, getTitle(), 542 JOptionPane.ERROR_MESSAGE); 543 return null; 544 } 545 } 546 547 return obj; 548 } 549 550 /** Returns the new dataset created. */ 551 public DataFormat getObject() { 552 return newObject; 553 } 554 555 /** Returns the parent group of the new dataset. */ 556 public Group getParentGroup() { 557 return (Group) groupList.get(parentChoice.getSelectedIndex()); 558 } 559 560 public void changedUpdate(DocumentEvent arg0) { 561 } 562 563 public void insertUpdate(DocumentEvent e) { 564 targetObject.setEnabled(true); 565 getTargetFileObjs(); 566 } 567 568 public void removeUpdate(DocumentEvent arg0) { 569 targetObject.setEnabled(true); 570 getTargetFileObjs(); 571 } 572 573 //Retrieving objects from Target File. 574 private void getTargetFileObjs(){ 575 FileFormat fileFormatC = null; 576 int fileAccessID = FileFormat.FILE_CREATE_OPEN; 577 String filename = null; 578 filename = targetFile.getText(); 579 580 if (filename == null || filename.length()<1) { 581 return; 582 } 583 584 //Check if the target File is not the current file. 585 String CurrentFileName = fileFormat.getAbsolutePath(); 586 if(CurrentFileName.equals(filename)) 587 targetObject.setEnabled(false); 588 589 //Check if the target File is open in treeView 590 if (isFileOpen(filename)) { 591 return; 592 } 593 594 File choosedFile = new File(filename); 595 596 if (!choosedFile.exists()) { 597 targetObject.setEnabled(false); 598 return; 599 } 600 FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5); 601 try { 602 //h5format.close(); 603 fileFormatC = h5format.createInstance(filename, fileAccessID); 604 fileFormatC.open(); //open the file 605 606 } 607 catch (Exception ex) { 608 targetObject.setEnabled(false); 609 toolkit.beep(); 610 JOptionPane.showMessageDialog(this,"Invalid File Format", getTitle(), 611 JOptionPane.ERROR_MESSAGE); 612 return; 613 } 614 615 //getting the list of objects from the file:- 616 retriveObjects(fileFormatC); 617 618 try { 619 fileFormatC.close(); 620 } 621 catch (Exception ex) { 622 log.debug("FileFormat close:", ex); 623 } 624 } 625 626 //Function to check if the target File is open in treeView 627 private boolean isFileOpen(String filename) 628 { 629 boolean isOpen = false; 630 FileFormat theFile = null; 631 632 Iterator<?> iterator = fileList.iterator(); 633 while(iterator.hasNext()) { 634 theFile = (FileFormat)iterator.next(); 635 if (theFile.getFilePath().equals(filename)) { 636 isOpen = true; 637 if(!theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))){ 638 targetObject.setEnabled(false); 639 } 640 retriveObjects(theFile); 641 break; 642 } 643 } // while(iterator.hasNext()) 644 645 return isOpen; 646 } 647 648 public void itemStateChanged(ItemEvent e) { 649 Object source = e.getSource(); 650 651 if (source instanceof JRadioButton) { 652 if (source.equals(hardLink) || source.equals(softLink) || source.equals(externalLink)) { 653 if (hardLink.isSelected()) { 654 targetFile.setEnabled(false); 655 targetFileButton.setEnabled(false); 656 targetObject.setEnabled(true); 657 targetObject.setEditable(false); 658 retriveObjects(fileFormat); 659 } 660 else if (softLink.isSelected()) { 661 targetFile.setEnabled(false); 662 targetFileButton.setEnabled(false); 663 targetObject.setEnabled(true); 664 targetObject.setEditable(true); 665 retriveObjects(fileFormat); 666 } 667 else if (externalLink.isSelected()) { 668 targetFile.setEnabled(true); 669 targetFileButton.setEnabled(true); 670 targetObject.setEnabled(true); 671 targetObject.setEditable(true); 672 targetObject.removeAllItems(); 673 } 674 } 675 } 676 } 677 678 //getting the list of objects from the file:- 679 private void retriveObjects(FileFormat file) { 680 List<Object> objsFile = breadthFirstUserObjects(file.getRootNode()); 681 List<HObject> groupListFile = new Vector<HObject>(objsFile.size()); 682 HObject obj = null; 683 Iterator<Object> iterator = objsFile.iterator(); 684 List<Object> objListFile = objsFile; 685 String full_name = null; 686 int idx_root = -1, idx = -1; 687 targetObject.removeAllItems(); 688 while (iterator.hasNext()) { 689 obj = (HObject) iterator.next(); 690 idx++; 691 692 if (obj instanceof Group) { 693 Group g = (Group) obj; 694 groupListFile.add(obj); 695 if (g.isRoot()) { 696 full_name = HObject.separator; 697 idx_root = idx; 698 } 699 else { 700 full_name = g.getPath() + g.getName() + HObject.separator; 701 } 702 } 703 else { 704 full_name = obj.getPath() + obj.getName(); 705 } 706 targetObject.addItem(full_name); 707 } 708 targetObject.removeItemAt(idx_root); 709 objListFile.remove(idx_root); 710 } 711 712} 713