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 /** 551 * Returns the new dataset created. 552 * 553 * @return The new Dataset created 554 */ 555 public DataFormat getObject() { 556 return newObject; 557 } 558 559 /** 560 * Returns the parent group of the new dataset. 561 * 562 * @return The parent group of the new Dataset 563 */ 564 public Group getParentGroup() { 565 return (Group) groupList.get(parentChoice.getSelectedIndex()); 566 } 567 568 public void changedUpdate(DocumentEvent arg0) { 569 } 570 571 public void insertUpdate(DocumentEvent e) { 572 targetObject.setEnabled(true); 573 getTargetFileObjs(); 574 } 575 576 public void removeUpdate(DocumentEvent arg0) { 577 targetObject.setEnabled(true); 578 getTargetFileObjs(); 579 } 580 581 //Retrieving objects from Target File. 582 private void getTargetFileObjs(){ 583 FileFormat fileFormatC = null; 584 int fileAccessID = FileFormat.FILE_CREATE_OPEN; 585 String filename = null; 586 filename = targetFile.getText(); 587 588 if (filename == null || filename.length()<1) { 589 return; 590 } 591 592 //Check if the target File is not the current file. 593 String CurrentFileName = fileFormat.getAbsolutePath(); 594 if(CurrentFileName.equals(filename)) 595 targetObject.setEnabled(false); 596 597 //Check if the target File is open in treeView 598 if (isFileOpen(filename)) { 599 return; 600 } 601 602 File choosedFile = new File(filename); 603 604 if (!choosedFile.exists()) { 605 targetObject.setEnabled(false); 606 return; 607 } 608 FileFormat h5format = FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5); 609 try { 610 //h5format.close(); 611 fileFormatC = h5format.createInstance(filename, fileAccessID); 612 fileFormatC.open(); //open the file 613 614 } 615 catch (Exception ex) { 616 targetObject.setEnabled(false); 617 toolkit.beep(); 618 JOptionPane.showMessageDialog(this,"Invalid File Format", getTitle(), 619 JOptionPane.ERROR_MESSAGE); 620 return; 621 } 622 623 //getting the list of objects from the file:- 624 retriveObjects(fileFormatC); 625 626 try { 627 fileFormatC.close(); 628 } 629 catch (Exception ex) { 630 log.debug("FileFormat close:", ex); 631 } 632 } 633 634 //Function to check if the target File is open in treeView 635 private boolean isFileOpen(String filename) 636 { 637 boolean isOpen = false; 638 FileFormat theFile = null; 639 640 Iterator<?> iterator = fileList.iterator(); 641 while(iterator.hasNext()) { 642 theFile = (FileFormat)iterator.next(); 643 if (theFile.getFilePath().equals(filename)) { 644 isOpen = true; 645 if(!theFile.isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5))){ 646 targetObject.setEnabled(false); 647 } 648 retriveObjects(theFile); 649 break; 650 } 651 } // while(iterator.hasNext()) 652 653 return isOpen; 654 } 655 656 public void itemStateChanged(ItemEvent e) { 657 Object source = e.getSource(); 658 659 if (source instanceof JRadioButton) { 660 if (source.equals(hardLink) || source.equals(softLink) || source.equals(externalLink)) { 661 if (hardLink.isSelected()) { 662 targetFile.setEnabled(false); 663 targetFileButton.setEnabled(false); 664 targetObject.setEnabled(true); 665 targetObject.setEditable(false); 666 retriveObjects(fileFormat); 667 } 668 else if (softLink.isSelected()) { 669 targetFile.setEnabled(false); 670 targetFileButton.setEnabled(false); 671 targetObject.setEnabled(true); 672 targetObject.setEditable(true); 673 retriveObjects(fileFormat); 674 } 675 else if (externalLink.isSelected()) { 676 targetFile.setEnabled(true); 677 targetFileButton.setEnabled(true); 678 targetObject.setEnabled(true); 679 targetObject.setEditable(true); 680 targetObject.removeAllItems(); 681 } 682 } 683 } 684 } 685 686 //getting the list of objects from the file:- 687 private void retriveObjects(FileFormat file) { 688 List<Object> objsFile = breadthFirstUserObjects(file.getRootNode()); 689 List<HObject> groupListFile = new Vector<HObject>(objsFile.size()); 690 HObject obj = null; 691 Iterator<Object> iterator = objsFile.iterator(); 692 List<Object> objListFile = objsFile; 693 String full_name = null; 694 int idx_root = -1, idx = -1; 695 targetObject.removeAllItems(); 696 while (iterator.hasNext()) { 697 obj = (HObject) iterator.next(); 698 idx++; 699 700 if (obj instanceof Group) { 701 Group g = (Group) obj; 702 groupListFile.add(obj); 703 if (g.isRoot()) { 704 full_name = HObject.separator; 705 idx_root = idx; 706 } 707 else { 708 full_name = g.getPath() + g.getName() + HObject.separator; 709 } 710 } 711 else { 712 full_name = obj.getPath() + obj.getName(); 713 } 714 targetObject.addItem(full_name); 715 } 716 targetObject.removeItemAt(idx_root); 717 objListFile.remove(idx_root); 718 } 719 720} 721