001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.core.partition.impl.btree.gui; 021 022 023 import java.awt.BorderLayout; 024 import java.awt.Dimension; 025 import java.awt.Toolkit; 026 import java.awt.Window; 027 import java.awt.event.ActionEvent; 028 import java.awt.event.ActionListener; 029 import java.io.File; 030 import java.io.FileNotFoundException; 031 import java.io.FileReader; 032 import java.util.HashMap; 033 import java.util.Iterator; 034 import java.util.Map; 035 import java.util.Stack; 036 037 import javax.naming.NamingException; 038 import javax.naming.directory.SearchControls; 039 import javax.swing.JFileChooser; 040 import javax.swing.JFrame; 041 import javax.swing.JLabel; 042 import javax.swing.JMenu; 043 import javax.swing.JMenuBar; 044 import javax.swing.JMenuItem; 045 import javax.swing.JOptionPane; 046 import javax.swing.JPanel; 047 import javax.swing.JScrollPane; 048 import javax.swing.JSeparator; 049 import javax.swing.JSplitPane; 050 import javax.swing.JTabbedPane; 051 import javax.swing.JTable; 052 import javax.swing.JTextArea; 053 import javax.swing.JTree; 054 import javax.swing.event.TreeSelectionEvent; 055 import javax.swing.event.TreeSelectionListener; 056 import javax.swing.table.DefaultTableModel; 057 import javax.swing.tree.DefaultTreeModel; 058 import javax.swing.tree.TreeModel; 059 import javax.swing.tree.TreeNode; 060 import javax.swing.tree.TreePath; 061 062 import org.apache.directory.server.core.interceptor.context.AddOperationContext; 063 import org.apache.directory.server.core.partition.impl.btree.BTreePartition; 064 import org.apache.directory.server.i18n.I18n; 065 import org.apache.directory.server.xdbm.Index; 066 import org.apache.directory.server.xdbm.IndexCursor; 067 import org.apache.directory.server.xdbm.IndexEntry; 068 import org.apache.directory.shared.ldap.entry.DefaultServerEntry; 069 import org.apache.directory.shared.ldap.entry.ServerEntry; 070 import org.apache.directory.shared.ldap.filter.ExprNode; 071 import org.apache.directory.shared.ldap.filter.FilterParser; 072 import org.apache.directory.shared.ldap.ldif.LdifEntry; 073 import org.apache.directory.shared.ldap.ldif.LdifReader; 074 import org.apache.directory.shared.ldap.message.AliasDerefMode; 075 import org.apache.directory.shared.ldap.name.DN; 076 import org.apache.directory.shared.ldap.schema.SchemaManager; 077 import org.apache.directory.shared.ldap.util.StringTools; 078 import org.slf4j.Logger; 079 import org.slf4j.LoggerFactory; 080 081 082 /** 083 * The frame for the database. 084 * 085 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 086 * @version $Rev: 927404 $ 087 */ 088 public class PartitionFrame extends JFrame 089 { 090 private static final Logger LOG = LoggerFactory.getLogger( PartitionFrame.class ); 091 092 private static final long serialVersionUID = 4049353102291513657L; 093 094 // Swing Stuff 095 private JLabel statusBar = new JLabel( "Ready" ); 096 private JPanel mainPnl = new JPanel(); 097 private JSplitPane splitPane = new JSplitPane(); 098 private JTabbedPane tabbedPane = new JTabbedPane(); 099 private JPanel entryPnl = new JPanel(); 100 private JPanel idxPnl = new JPanel(); 101 private JScrollPane treePane = new JScrollPane(); 102 private JTree tree = new JTree(); 103 private JScrollPane entryPane = new JScrollPane(); 104 private JTable entryTbl = new JTable(); 105 private JScrollPane idxPane = new JScrollPane(); 106 private JTable idxTbl = new JTable(); 107 private JMenu searchMenu = new JMenu(); 108 private JMenuItem annotate = new JMenuItem(); 109 private JMenuItem run = new JMenuItem(); 110 private JMenuItem debug = new JMenuItem(); 111 private JMenu indices = new JMenu(); 112 113 // Non Swing Stuff 114 private BTreePartition<Long> partition; 115 private boolean doCleanUp; 116 private Map<Long, EntryNode> nodes; 117 private EntryNode root; 118 119 /** A handle on the global schemaManager */ 120 private SchemaManager schemaManager; 121 122 123 /** 124 * Creates new form JFrame 125 * 126 * @param db the partition to view 127 * @throws NamingException if there are problems accessing the partition 128 */ 129 public PartitionFrame( BTreePartition<Long> db, SchemaManager schemaManager ) throws Exception 130 { 131 partition = db; 132 this.schemaManager = schemaManager; 133 134 initialize(); 135 buildIndicesMenu( partition ); 136 pack(); 137 load(); 138 } 139 140 141 /** 142 * This method is called from within the constructor to initialize the form 143 * 144 * @throws NamingException on partition access errors 145 */ 146 private void initialize() throws Exception 147 { 148 mainPnl.setBorder( null ); 149 mainPnl.setLayout( new java.awt.BorderLayout() ); 150 mainPnl.add( splitPane, java.awt.BorderLayout.CENTER ); 151 splitPane.add( tabbedPane, javax.swing.JSplitPane.RIGHT ); 152 splitPane.add( treePane, javax.swing.JSplitPane.LEFT ); 153 tabbedPane.add( entryPnl, "Entry Attributes" ); 154 tabbedPane.add( idxPnl, "Entry Indices" ); 155 156 entryPnl.setLayout( new java.awt.BorderLayout() ); 157 entryPnl.add( entryPane, java.awt.BorderLayout.CENTER ); 158 159 idxPnl.setLayout( new java.awt.BorderLayout() ); 160 idxPnl.add( idxPane, java.awt.BorderLayout.CENTER ); 161 162 getContentPane().setLayout( new java.awt.BorderLayout() ); 163 JPanel content = new JPanel(); 164 content.setPreferredSize( new java.awt.Dimension( 798, 461 ) ); 165 content.setLayout( new java.awt.BorderLayout() ); 166 content.setBorder( javax.swing.BorderFactory.createEtchedBorder() ); 167 content.add( mainPnl, java.awt.BorderLayout.NORTH ); 168 getContentPane().add( content, BorderLayout.CENTER ); 169 // set title 170 setTitle( "Partition: " + this.partition.getSuffixDn().getName() ); 171 // add status bar 172 getContentPane().add( statusBar, BorderLayout.SOUTH ); 173 // add menu bar 174 JMenuBar menuBar = new JMenuBar(); 175 176 // -------------------------------------------------------------------- 177 // 'Backend' Menu 178 // -------------------------------------------------------------------- 179 180 JMenu backendMenu = new JMenu( "Backend" ); 181 backendMenu.setText( "Partition" ); 182 backendMenu.setBackground( new java.awt.Color( 205, 205, 205 ) ); 183 backendMenu.setMnemonic( 'B' ); 184 185 // create Import menu item 186 JMenuItem add = new JMenuItem( "Add" ); 187 backendMenu.add( add ); 188 add.setMnemonic( 'A' ); 189 add.setBackground( new java.awt.Color( 205, 205, 205 ) ); 190 add.addActionListener( new ActionListener() 191 { 192 public void actionPerformed( ActionEvent e ) 193 { 194 doAddDialog(); 195 } 196 } ); 197 198 // create Import menu item 199 JMenuItem importItem = new JMenuItem( "Import" ); 200 backendMenu.add( importItem ); 201 importItem.setMnemonic( 'I' ); 202 importItem.setBackground( new java.awt.Color( 205, 205, 205 ) ); 203 importItem.addActionListener( new ActionListener() 204 { 205 public void actionPerformed( ActionEvent e ) 206 { 207 doImport(); 208 } 209 } ); 210 211 // create Exit menu item 212 JMenuItem exit = new JMenuItem( "Exit" ); 213 backendMenu.add( exit ); 214 exit.setMnemonic( 'E' ); 215 exit.setBackground( new java.awt.Color( 205, 205, 205 ) ); 216 exit.addActionListener( new ActionListener() 217 { 218 public void actionPerformed( ActionEvent e ) 219 { 220 try 221 { 222 exitForm(); 223 } 224 catch ( Exception e1 ) 225 { 226 e1.printStackTrace(); 227 } 228 } 229 } ); 230 231 // create About menu item 232 JMenu helpMenu = new JMenu( "Help" ); 233 helpMenu.setMnemonic( 'H' ); 234 JMenuItem about = new JMenuItem( "About" ); 235 about.setMnemonic( 'A' ); 236 about.setBackground( new java.awt.Color( 205, 205, 205 ) ); 237 about.addActionListener( new ActionListener() 238 { 239 public void actionPerformed( ActionEvent e ) 240 { 241 AboutDialog aboutDialog = new AboutDialog( PartitionFrame.this, true ); 242 PartitionFrame.this.centerOnScreen( aboutDialog ); 243 aboutDialog.setVisible( true ); 244 } 245 } ); 246 helpMenu.setBackground( new java.awt.Color( 205, 205, 205 ) ); 247 helpMenu.add( about ); 248 249 // create Save menu item 250 // create Print menu item 251 menuBar.setBackground( new java.awt.Color( 196, 197, 203 ) ); 252 menuBar.add( backendMenu ); 253 menuBar.add( searchMenu ); 254 menuBar.add( indices ); 255 menuBar.add( helpMenu ); 256 // sets menu bar 257 setJMenuBar( menuBar ); 258 setBounds( new java.awt.Rectangle( 0, 0, 802, 515 ) ); 259 setSize( new java.awt.Dimension( 802, 515 ) ); 260 setResizable( true ); 261 262 addWindowListener( new java.awt.event.WindowAdapter() 263 { 264 public void windowClosing( java.awt.event.WindowEvent evt ) 265 { 266 try 267 { 268 exitForm(); 269 } 270 catch ( Exception e ) 271 { 272 e.printStackTrace(); 273 } 274 } 275 } ); 276 277 treePane.getViewport().add( tree ); 278 tree.setBounds( new java.awt.Rectangle( 6, 184, 82, 80 ) ); 279 tree.setShowsRootHandles( true ); 280 tree.setToolTipText( "DB DIT" ); 281 tree.setScrollsOnExpand( true ); 282 tree.getSelectionModel().addTreeSelectionListener( new TreeSelectionListener() 283 { 284 public void valueChanged( TreeSelectionEvent e ) 285 { 286 TreePath path = e.getNewLeadSelectionPath(); 287 288 if ( path == null ) 289 { 290 return; 291 } 292 293 Object last = path.getLastPathComponent(); 294 try 295 { 296 if ( last instanceof EntryNode ) 297 { 298 displayEntry( ( ( EntryNode ) last ).getEntryId(), ( ( EntryNode ) last ).getLdapEntry() ); 299 } 300 } 301 catch ( Exception ex ) 302 { 303 ex.printStackTrace(); 304 } 305 } 306 } ); 307 308 entryPane.getViewport().add( entryTbl ); 309 entryTbl.setBounds( new java.awt.Rectangle( 321, 103, 32, 32 ) ); 310 311 idxPane.getViewport().add( idxTbl ); 312 idxTbl.setBounds( new java.awt.Rectangle( 429, 134, 32, 32 ) ); 313 314 treePane.setSize( new java.awt.Dimension( 285, 435 ) ); 315 treePane.setPreferredSize( new java.awt.Dimension( 285, 403 ) ); 316 searchMenu.setText( "Search" ); 317 searchMenu.setBackground( new java.awt.Color( 205, 205, 205 ) ); 318 searchMenu.add( run ); 319 searchMenu.add( debug ); 320 searchMenu.add( annotate ); 321 322 ActionListener searchHandler = new ActionListener() 323 { 324 public void actionPerformed( ActionEvent an_event ) 325 { 326 LOG.debug( "action command = {}", an_event.getActionCommand() ); 327 328 try 329 { 330 doFilterDialog( an_event.getActionCommand() ); 331 } 332 catch ( Exception e ) 333 { 334 e.printStackTrace(); 335 } 336 } 337 }; 338 339 annotate.setText( FilterDialog.ANNOTATE_MODE ); 340 annotate.setActionCommand( FilterDialog.ANNOTATE_MODE ); 341 annotate.setBackground( new java.awt.Color( 205, 205, 205 ) ); 342 annotate.addActionListener( searchHandler ); 343 344 run.setText( FilterDialog.RUN_MODE ); 345 run.setActionCommand( FilterDialog.RUN_MODE ); 346 run.setBackground( new java.awt.Color( 205, 205, 205 ) ); 347 run.addActionListener( searchHandler ); 348 349 debug.setText( FilterDialog.DEBUG_MODE ); 350 debug.setActionCommand( FilterDialog.DEBUG_MODE ); 351 debug.setBackground( new java.awt.Color( 205, 205, 205 ) ); 352 debug.addActionListener( searchHandler ); 353 354 indices.setText( "Indices" ); 355 indices.setBackground( new java.awt.Color( 205, 205, 205 ) ); 356 } 357 358 359 private void centerOnScreen( Window window ) 360 { 361 Dimension frameSize = window.getSize(); 362 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 363 364 frameSize.height = ( ( frameSize.height > screenSize.height ) ? screenSize.height : frameSize.height ); 365 frameSize.width = ( ( frameSize.width > screenSize.width ) ? screenSize.width : frameSize.width ); 366 window.setLocation( ( screenSize.width - frameSize.width ) / 2, ( screenSize.height - frameSize.height ) / 2 ); 367 } 368 369 370 /** 371 * Displays a entry addition dialog. 372 */ 373 public void doAddDialog() 374 { 375 try 376 { 377 TreePath path = tree.getSelectionModel().getSelectionPath(); 378 String parentDn = partition.getSuffixDn().getName(); 379 380 if ( null != path ) 381 { 382 Object last = path.getLastPathComponent(); 383 384 if ( last instanceof EntryNode ) 385 { 386 parentDn = ( ( EntryNode ) last ).getEntryDn(); 387 } 388 } 389 390 if ( null == parentDn ) 391 { 392 JOptionPane.showMessageDialog( this, "Must select a parent entry to add a child to!" ); 393 return; 394 } 395 396 AddEntryDialog dialog = new AddEntryDialog( this, false, schemaManager ); 397 dialog.setParentDn( parentDn ); 398 399 centerOnScreen( dialog ); 400 dialog.setEnabled( true ); 401 dialog.setVisible( true ); 402 } 403 catch ( Exception e ) 404 { 405 e.printStackTrace(); 406 } 407 } 408 409 410 /** 411 * Gets the DN of the DIT node selected in the tree view. 412 * 413 * @return the DN of the selected tree node or the root Dn of the tree if 414 * nothing has been selected yet. 415 * @throws NamingException on partition access errors 416 */ 417 public String getSelectedDn() throws Exception 418 { 419 TreePath path = tree.getSelectionModel().getSelectionPath(); 420 421 if ( null == path ) 422 { 423 return partition.getSuffixDn().getName(); 424 } 425 426 Object last = path.getLastPathComponent(); 427 String base = null; 428 429 if ( last instanceof EntryNode ) 430 { 431 try 432 { 433 base = ( ( EntryNode ) last ).getEntryDn(); 434 } 435 catch ( NamingException e ) 436 { 437 e.printStackTrace(); 438 } 439 } 440 else 441 { 442 base = partition.getSuffixDn().getName(); 443 } 444 445 return base; 446 } 447 448 449 public void doImport() 450 { 451 FileReader in; 452 JFileChooser chooser = new JFileChooser(); 453 int choice = chooser.showOpenDialog( this ); 454 File selected = chooser.getSelectedFile(); 455 456 if ( JFileChooser.APPROVE_OPTION != choice ) 457 { 458 return; 459 } 460 461 try 462 { 463 in = new FileReader( selected ); 464 465 for ( LdifEntry entry : new LdifReader( in ) ) 466 { 467 String updn = entry.getDn().getName(); 468 469 DN ndn = new DN( StringTools.deepTrimToLower( updn ) ); 470 471 ServerEntry attrs = new DefaultServerEntry( schemaManager, entry.getEntry() ); 472 473 if ( null == partition.getEntryId( ndn.getNormName() ) ) 474 { 475 partition.add( new AddOperationContext( null, attrs ) ); 476 load(); 477 } 478 } 479 } 480 catch ( NamingException e ) 481 { 482 // @todo display popup with error here! 483 e.printStackTrace(); 484 } 485 catch ( FileNotFoundException e ) 486 { 487 // @todo display popup with error here! 488 e.printStackTrace(); 489 } 490 catch ( Exception e ) 491 { 492 // @todo display popup with error here! 493 e.printStackTrace(); 494 } 495 } 496 497 498 /** 499 * Exit the Application 500 */ 501 private void exitForm() throws Exception 502 { 503 setEnabled( false ); 504 setVisible( false ); 505 dispose(); 506 507 if ( doCleanUp && partition != null ) 508 { 509 try 510 { 511 partition.sync(); 512 partition.destroy(); 513 } 514 catch ( NamingException e ) 515 { 516 e.printStackTrace(); 517 } 518 519 System.exit( 0 ); 520 } 521 } 522 523 524 public void doRunDebugAnnotate( FilterDialog dialog, String mode ) 525 { 526 try 527 { 528 if ( mode.equals( FilterDialog.RUN_MODE ) ) 529 { 530 doRun( dialog.getFilter(), dialog.getScope(), dialog.getBase(), dialog.getLimit() ); 531 } 532 else if ( mode.equals( FilterDialog.DEBUG_MODE ) ) 533 { 534 doDebug( dialog.getFilter(), dialog.getScope(), dialog.getBase(), dialog.getLimit() ); 535 } 536 else if ( mode.equals( FilterDialog.ANNOTATE_MODE ) ) 537 { 538 if ( doAnnotate( dialog.getFilter() ) ) 539 { 540 // continue 541 } 542 else 543 { 544 // We failed don't loose users filter buf 545 // allow user to make edits. 546 return; 547 } 548 549 LOG.debug( "call to annotate" ); 550 } 551 else 552 { 553 throw new RuntimeException( I18n.err( I18n.ERR_730 ) ); 554 } 555 } 556 catch ( Exception e ) 557 { 558 // @todo show error popup here! 559 e.printStackTrace(); 560 } 561 } 562 563 564 public void doFilterDialog( final String mode ) throws Exception 565 { 566 final FilterDialog dialog = new FilterDialog( mode, this, true ); 567 568 if ( tree.getSelectionModel().getSelectionPath() != null ) 569 { 570 dialog.setBase( getSelectedDn() ); 571 } 572 else 573 { 574 dialog.setBase( partition.getSuffixDn().getName() ); 575 } 576 577 dialog.addActionListener( new ActionListener() 578 { 579 public void actionPerformed( ActionEvent an_event ) 580 { 581 String cmd = an_event.getActionCommand(); 582 583 if ( cmd.equals( FilterDialog.SEARCH_CMD ) ) 584 { 585 doRunDebugAnnotate( dialog, mode ); 586 } 587 else if ( cmd.equals( FilterDialog.CANCEL_CMD ) ) 588 { 589 // Do nothing! Just exit dialog. 590 } 591 else 592 { 593 throw new RuntimeException( I18n.err( I18n.ERR_731, cmd ) ); 594 } 595 596 dialog.setVisible( false ); 597 dialog.dispose(); 598 } 599 } ); 600 601 //Center the frame on screen 602 dialog.setSize( 456, 256 ); 603 centerOnScreen( dialog ); 604 dialog.setEnabled( true ); 605 dialog.setVisible( true ); 606 } 607 608 609 public boolean doRun( String filter, String scope, String base, String limit ) throws Exception 610 { 611 if ( LOG.isDebugEnabled() ) 612 { 613 LOG.debug( "Search attempt using filter '" + filter + "' " + "with scope '" + scope 614 + "' and a return limit of '" + limit + "'" ); 615 } 616 617 ExprNode root; 618 619 try 620 { 621 root = FilterParser.parse( filter ); 622 } 623 catch ( Exception e ) 624 { 625 e.printStackTrace(); 626 JTextArea text = new JTextArea(); 627 String msg = e.getLocalizedMessage(); 628 629 if ( msg.length() > 1024 ) 630 { 631 msg = msg.substring( 0, 1024 ) + "\n. . . truncated . . ."; 632 } 633 634 text.setText( msg ); 635 text.setEnabled( false ); 636 JOptionPane.showMessageDialog( null, text, "Syntax Error", JOptionPane.ERROR_MESSAGE ); 637 return false; 638 } 639 640 SearchControls ctls = new SearchControls(); 641 642 if ( scope.equals( FilterDialog.BASE_SCOPE ) ) 643 { 644 ctls.setSearchScope( SearchControls.OBJECT_SCOPE ); 645 } 646 else if ( scope.equals( FilterDialog.SINGLE_SCOPE ) ) 647 { 648 ctls.setSearchScope( SearchControls.ONELEVEL_SCOPE ); 649 } 650 else if ( scope.equals( FilterDialog.SUBTREE_SCOPE ) ) 651 { 652 ctls.setSearchScope( SearchControls.SUBTREE_SCOPE ); 653 } 654 else 655 { 656 throw new RuntimeException( "Unexpected scope parameter: " + scope ); 657 } 658 659 int limitMax = Integer.MAX_VALUE; 660 if ( !limit.equals( FilterDialog.UNLIMITED ) ) 661 { 662 limitMax = Integer.parseInt( limit ); 663 } 664 665 IndexCursor<Long, ServerEntry, Long> cursor = partition.getSearchEngine().cursor( new DN( base ), 666 AliasDerefMode.DEREF_ALWAYS, root, ctls ); 667 String[] cols = new String[2]; 668 cols[0] = "id"; 669 cols[1] = "dn"; 670 DefaultTableModel tableModel = new DefaultTableModel( cols, 0 ); 671 Object[] row = new Object[2]; 672 int count = 0; 673 while ( cursor.next() && count < limitMax ) 674 { 675 IndexEntry rec = ( IndexEntry ) cursor.get(); 676 row[0] = rec.getId(); 677 row[1] = partition.getEntryDn( ( Long ) row[0] ); 678 tableModel.addRow( row ); 679 count++; 680 } 681 682 SearchResultDialog results = new SearchResultDialog( this, false ); 683 StringBuffer buf = new StringBuffer(); 684 buf.append( "base: " ); 685 buf.append( base ); 686 buf.append( "\n" ); 687 buf.append( "scope: " ); 688 buf.append( scope ); 689 buf.append( "\n" ); 690 buf.append( "limit: " ); 691 buf.append( limit ); 692 buf.append( "\n" ); 693 buf.append( "total: " ); 694 buf.append( count ); 695 buf.append( "\n" ); 696 buf.append( "filter:\n" ); 697 buf.append( filter ); 698 buf.append( "\n" ); 699 results.setFilter( buf.toString() ); 700 701 TreeNode astRoot = new ASTNode( null, root ); 702 TreeModel treeModel = new DefaultTreeModel( astRoot, true ); 703 results.setTreeModel( treeModel ); 704 results.setTableModel( tableModel ); 705 centerOnScreen( results ); 706 results.setVisible( true ); 707 return true; 708 } 709 710 711 public void doDebug( String filter, String scope, String base, String limit ) 712 { 713 if ( LOG.isDebugEnabled() ) 714 { 715 LOG.debug( "debug attempt using base '" + base + "' filter '" + filter + "' " + "with scope '" + scope 716 + "' and a return limit of '" + limit + "'" ); 717 } 718 719 LOG.warn( "NOT IMPLMENTED YET" ); 720 } 721 722 723 public void selectTreeNode( Long id ) 724 { 725 Stack<TreeNode> stack = new Stack<TreeNode>(); 726 Object[] comps; 727 TreeNode parent = nodes.get( id ); 728 729 while ( parent != null && ( parent != parent.getParent() ) ) 730 { 731 stack.push( parent ); 732 parent = parent.getParent(); 733 } 734 735 if ( stack.size() == 0 ) 736 { 737 comps = new Object[1]; 738 comps[0] = root; 739 } 740 else 741 { 742 comps = new Object[stack.size()]; 743 } 744 745 for ( int ii = 0; stack.size() > 0 && ii < comps.length; ii++ ) 746 { 747 comps[ii] = stack.pop(); 748 } 749 750 TreePath path = new TreePath( comps ); 751 tree.scrollPathToVisible( path ); 752 tree.getSelectionModel().setSelectionPath( path ); 753 tree.validate(); 754 } 755 756 757 public boolean doAnnotate( String filter ) throws Exception 758 { 759 ExprNode root; 760 761 try 762 { 763 root = FilterParser.parse( filter ); 764 } 765 catch ( Exception e ) 766 { 767 JTextArea text = new JTextArea(); 768 String msg = e.getLocalizedMessage(); 769 770 if ( msg.length() > 1024 ) 771 { 772 msg = msg.substring( 0, 1024 ) + "\n. . . truncated . . ."; 773 } 774 775 text.setText( msg ); 776 text.setEnabled( false ); 777 JOptionPane.showMessageDialog( null, text, "Syntax Error", JOptionPane.ERROR_MESSAGE ); 778 return false; 779 } 780 781 AnnotatedFilterTreeDialog treeDialog = new AnnotatedFilterTreeDialog( PartitionFrame.this, false ); 782 treeDialog.setFilter( filter ); 783 784 partition.getSearchEngine().getOptimizer().annotate( root ); 785 TreeNode astRoot = new ASTNode( null, root ); 786 TreeModel model = new DefaultTreeModel( astRoot, true ); 787 treeDialog.setModel( model ); 788 treeDialog.setVisible( true ); 789 return true; 790 } 791 792 793 /** 794 * Shows a dialog to display and scan indices. 795 * 796 * @param idxAttr the name of the index or its attribute 797 * @throws Exception if the indices cannot be accessed 798 */ 799 public void showIndexDialog( String idxAttr ) throws Exception 800 { 801 Index index; 802 boolean isSystem = partition.hasSystemIndexOn( idxAttr ); 803 804 if ( isSystem ) 805 { 806 index = partition.getSystemIndex( idxAttr ); 807 } 808 else 809 { 810 index = partition.getUserIndex( idxAttr ); 811 } 812 813 if ( index != null ) 814 { 815 IndexDialog dialog = new IndexDialog( this, false, index ); 816 centerOnScreen( dialog ); 817 dialog.setEnabled( true ); 818 dialog.setVisible( true ); 819 } 820 } 821 822 823 public void buildIndicesMenu( BTreePartition partition ) 824 { 825 JMenuItem item; 826 827 ActionListener listener = new ActionListener() 828 { 829 public void actionPerformed( ActionEvent event ) 830 { 831 try 832 { 833 showIndexDialog( event.getActionCommand() ); 834 } 835 catch ( Exception e ) 836 { 837 e.printStackTrace(); 838 } 839 } 840 }; 841 842 Iterator list = partition.getSystemIndices(); 843 while ( list.hasNext() ) 844 { 845 String idx = ( String ) list.next(); 846 item = new JMenuItem(); 847 item.setBackground( new java.awt.Color( 205, 205, 205 ) ); 848 indices.add( item ); 849 item.setText( idx ); 850 item.setActionCommand( idx ); 851 item.addActionListener( listener ); 852 } 853 854 indices.add( new JSeparator() ); 855 list = partition.getUserIndices(); 856 while ( list.hasNext() ) 857 { 858 String idx = ( String ) list.next(); 859 item = new JMenuItem(); 860 item.setBackground( new java.awt.Color( 205, 205, 205 ) ); 861 indices.add( item ); 862 item.setText( idx ); 863 item.setActionCommand( idx ); 864 item.addActionListener( listener ); 865 } 866 } 867 868 869 void displayEntry( Long id, ServerEntry entry ) throws Exception 870 { 871 String dn = partition.getEntryUpdn( id ); 872 AttributesTableModel model = new AttributesTableModel( entry, id, dn, false ); 873 entryTbl.setModel( model ); 874 875 // TODO use utility method to getIndices below 876 // model = new AttributesTableModel( partition.getIndices( id ), id, dn, false ); 877 // idxTbl.setModel( model ); 878 // 879 // validate(); 880 } 881 882 883 private void load() throws Exception 884 { 885 // boolean doFiltered = false; 886 nodes = new HashMap<Long, EntryNode>(); 887 888 ServerEntry suffix = partition.lookup( partition.getEntryId( partition.getSuffixDn().getNormName() ) ); 889 Long id = partition.getEntryId( partition.getSuffixDn().getName() ); 890 root = new EntryNode( id, null, partition, suffix, nodes ); 891 892 /* 893 int option = JOptionPane.showConfirmDialog( null, 894 "Would you like to filter leaf nodes on load?", "Use Filter?", 895 JOptionPane.OK_CANCEL_OPTION ); 896 doFiltered = option == JOptionPane.OK_OPTION; 897 898 if(doFiltered) { 899 SearchEngine engine = new SearchEngine(); 900 final FilterDialog dialog = 901 new FilterDialog(FilterDialog.LOAD_MODE, this, true); 902 dialog.addActionListener(new ActionListener() { 903 public void actionPerformed(ActionEvent e) { 904 dialog.setVisible(false); 905 dialog.dispose(); 906 } 907 }); 908 909 dialog.setBase(database.getSuffixDn().toString()); 910 dialog.setScope(FilterDialog.SUBTREE_SCOPE); 911 912 //Center the frame on screen 913 dialog.setSize(456, 256); 914 this.centerOnScreen( dialog ); 915 dialog.setEnabled(true); 916 dialog.setVisible(true); 917 918 FilterParser parser = new FilterParserImpl(); 919 parser.enableLogging(logger); 920 ExprNode exprNode = parser.parse(dialog.getFilter()); 921 922 int scope = -1; 923 String scopeStr = dialog.getScope(); 924 if(scopeStr == FilterDialog.BASE_SCOPE) { 925 scope = Backend.BASE_SCOPE; 926 } else if(scopeStr == FilterDialog.SINGLE_SCOPE) { 927 scope = Backend.SINGLE_SCOPE; 928 } else if(scopeStr == FilterDialog.SUBTREE_SCOPE) { 929 scope = Backend.SUBTREE_SCOPE; 930 } else { 931 throw new RuntimeException("Unrecognized scope"); 932 } 933 934 exprNode = 935 engine.addScopeNode(exprNode, dialog.getBase(), scope); 936 root = new EntryNode(null, database, 937 database.getSuffixEntry(), nodes, exprNode, engine); 938 } else { 939 root = new EntryNode(null, database, 940 database.getSuffixEntry(), nodes); 941 } 942 */ 943 944 DefaultTreeModel model = new DefaultTreeModel( root ); 945 tree.setModel( model ); 946 947 if ( isVisible() ) 948 { 949 tree.validate(); 950 } 951 } 952 953 954 public void setDoCleanUp( boolean doCleanUp ) 955 { 956 this.doCleanUp = doCleanUp; 957 } 958 }