View Javadoc

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