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.xdbm.tools;
21  
22  
23  import java.awt.Color;
24  import java.awt.Font;
25  import java.awt.Frame;
26  import java.awt.Panel;
27  import java.awt.event.*;
28  
29  import javax.swing.BorderFactory;
30  import javax.swing.BoxLayout;
31  import javax.swing.ButtonGroup;
32  import javax.swing.JButton;
33  import javax.swing.JDialog;
34  import javax.swing.JLabel;
35  import javax.swing.JOptionPane;
36  import javax.swing.JPanel;
37  import javax.swing.JRadioButton;
38  import javax.swing.JScrollPane;
39  import javax.swing.JTabbedPane;
40  import javax.swing.JTable;
41  import javax.swing.JTextArea;
42  import javax.swing.JTextField;
43  import javax.swing.border.TitledBorder;
44  import javax.swing.table.DefaultTableModel;
45  
46  import org.apache.directory.server.xdbm.Index;
47  import org.apache.directory.server.xdbm.IndexEntry;
48  import org.apache.directory.server.xdbm.ForwardIndexEntry;
49  import org.apache.directory.server.core.cursor.Cursor;
50  import org.apache.directory.server.core.entry.ServerEntry;
51  import org.apache.directory.shared.ldap.util.ExceptionUtils;
52  import org.apache.directory.shared.ldap.NotImplementedException;
53  
54  import org.slf4j.Logger;
55  import org.slf4j.LoggerFactory;
56  
57  
58  /**
59   * A dialog showing index values.
60   *
61   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
62   * @version $Rev: 639279 $
63   */
64  public class IndexDialog<K,O> extends JDialog
65  {
66      private static final Logger LOG = LoggerFactory.getLogger( IndexDialog.class );
67  
68      private static final long serialVersionUID = 3689917253680445238L;
69  
70      public static final String DEFAULT_CURSOR = "Default";
71      public static final String EQUALITY_CURSOR = "Equality";
72      public static final String GREATER_CURSOR = "Greater";
73      public static final String LESS_CURSOR = "Less";
74      public static final String REGEX_CURSOR = "Regex";
75  
76      private Panel mainPnl = new Panel();
77      private JTabbedPane tabbedPane = new JTabbedPane();
78      private JPanel listPnl = new JPanel();
79      private JPanel cursorPnl = new JPanel();
80      private JPanel resultsPnl = new JPanel();
81      private JScrollPane jScrollPane2 = new JScrollPane();
82      private JTable resultsTbl = new JTable();
83      private JPanel buttonPnl = new JPanel();
84      private JButton doneBut = new JButton();
85      private JLabel jLabel1 = new JLabel();
86      private JTextField keyText = new JTextField();
87      private JLabel jLabel2 = new JLabel();
88      private JButton scanBut = new JButton();
89  
90      private Index<K,O> index = null;
91  
92  
93      public IndexDialog( Frame parent, boolean modal, Index<K,O> index )
94      {
95          super( parent, modal );
96          this.index = index;
97          initGUI();
98      }
99      
100     
101     public IndexDialog( Index<K,O> index )
102     {
103         super();
104         this.index = index;
105         initGUI();
106     }
107 
108 
109     /**
110      * This method is called from within the constructor to initialize the
111      * form.
112      */
113     private void initGUI()
114     {
115         addWindowListener( new java.awt.event.WindowAdapter()
116         {
117             public void windowClosing( java.awt.event.WindowEvent evt )
118             {
119                 closeDialog();
120             }
121         } );
122 
123         pack();
124         setTitle( "Index On Attribute '" + index.getAttribute().getName() + "'" );
125         setBounds( new java.awt.Rectangle( 0, 0, 512, 471 ) );
126         getContentPane().add( mainPnl, java.awt.BorderLayout.CENTER );
127         mainPnl.setLayout( new java.awt.BorderLayout() );
128         mainPnl.add( tabbedPane, java.awt.BorderLayout.CENTER );
129         tabbedPane.add( listPnl, "Listing" );
130         listPnl.setLayout( new java.awt.GridBagLayout() );
131 
132         RadioButtonListener radioListener = new RadioButtonListener();
133         JRadioButton radioDefault = new JRadioButton( DEFAULT_CURSOR );
134         radioDefault.setActionCommand( DEFAULT_CURSOR );
135         radioDefault.setSelected( true );
136         radioDefault.addActionListener( radioListener );
137 
138         JRadioButton radioEquality = new JRadioButton( EQUALITY_CURSOR );
139         radioEquality.setActionCommand( EQUALITY_CURSOR );
140         radioEquality.addActionListener( radioListener );
141 
142         JRadioButton radioGreater = new JRadioButton( GREATER_CURSOR );
143         radioGreater.setActionCommand( GREATER_CURSOR );
144         radioGreater.addActionListener( radioListener );
145 
146         JRadioButton radioLess = new JRadioButton( LESS_CURSOR );
147         radioLess.setActionCommand( LESS_CURSOR );
148         radioLess.addActionListener( radioListener );
149 
150         JRadioButton radioRegex = new JRadioButton( REGEX_CURSOR );
151         radioRegex.setActionCommand( REGEX_CURSOR );
152         radioRegex.addActionListener( radioListener );
153 
154         ButtonGroup group = new ButtonGroup();
155         group.add( radioDefault );
156         group.add( radioEquality );
157         group.add( radioGreater );
158         group.add( radioLess );
159         group.add( radioRegex );
160 
161         JPanel radioPanel = new JPanel();
162         radioPanel.setLayout( new BoxLayout( radioPanel, BoxLayout.X_AXIS ) );
163         radioPanel.add( radioDefault );
164         radioPanel.add( radioEquality );
165         radioPanel.add( radioGreater );
166         radioPanel.add( radioLess );
167         radioPanel.add( radioRegex );
168 
169         listPnl.add( cursorPnl, new java.awt.GridBagConstraints( 0, 0, 1, 1, 1.0, 0.15,
170             java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 15, 0, 30, 0 ),
171             0, 0 ) );
172         listPnl.add( resultsPnl, new java.awt.GridBagConstraints( 0, 1, 1, 1, 1.0, 0.8,
173             java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 0, 0, 0, 0 ), 0,
174             0 ) );
175         listPnl.add( buttonPnl, new java.awt.GridBagConstraints( 0, 2, 1, 1, 1.0, 0.05,
176             java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 0, 0, 0, 0 ), 0,
177             0 ) );
178         cursorPnl.setLayout( new java.awt.GridBagLayout() );
179         cursorPnl.setBorder( javax.swing.BorderFactory.createTitledBorder( javax.swing.BorderFactory.createLineBorder(
180             new java.awt.Color( 153, 153, 153 ), 1 ), "Display Cursor Constraints",
181             javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP, new java.awt.Font(
182                 "SansSerif", 0, 14 ), new java.awt.Color( 60, 60, 60 ) ) );
183         cursorPnl.add( jLabel1, new java.awt.GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0,
184             java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE, new java.awt.Insets( 0, 15, 0, 10 ), 0,
185             0 ) );
186         cursorPnl.add( keyText, new java.awt.GridBagConstraints( 1, 1, 1, 1, 0.4, 0.0,
187             java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 5, 5, 5, 236 ), 0,
188             0 ) );
189         cursorPnl.add( jLabel2, new java.awt.GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0,
190             java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE, new java.awt.Insets( 0, 15, 0, 10 ), 0,
191             0 ) );
192         cursorPnl.add( radioPanel,
193             new java.awt.GridBagConstraints( 1, 0, 1, 1, 0.4, 0.0, java.awt.GridBagConstraints.WEST,
194                 java.awt.GridBagConstraints.NONE, new java.awt.Insets( 5, 5, 5, 0 ), 0, 0 ) );
195         resultsPnl.setLayout( new java.awt.BorderLayout() );
196         resultsPnl.setBorder( javax.swing.BorderFactory.createTitledBorder( javax.swing.BorderFactory.createLineBorder(
197             new java.awt.Color( 153, 153, 153 ), 1 ), "Scan Results", javax.swing.border.TitledBorder.LEADING,
198             javax.swing.border.TitledBorder.TOP, new java.awt.Font( "SansSerif", 0, 14 ), new java.awt.Color( 60, 60,
199                 60 ) ) );
200         resultsPnl.add( jScrollPane2, java.awt.BorderLayout.CENTER );
201         jScrollPane2.getViewport().add( resultsTbl );
202         buttonPnl.setLayout( new java.awt.FlowLayout( java.awt.FlowLayout.CENTER, 15, 5 ) );
203         buttonPnl.add( doneBut );
204         buttonPnl.add( scanBut );
205         doneBut.setText( "Done" );
206         doneBut.addActionListener( new ActionListener()
207         {
208             public void actionPerformed( ActionEvent e )
209             {
210                 closeDialog();
211             }
212         } );
213 
214         jLabel1.setText( "Key Constraint:" );
215         keyText.setText( "" );
216         keyText.setMinimumSize( new java.awt.Dimension( 130, 20 ) );
217         keyText.setPreferredSize( new java.awt.Dimension( 130, 20 ) );
218         keyText.setMaximumSize( new java.awt.Dimension( 130, 20 ) );
219         keyText.setFont( new java.awt.Font( "SansSerif", java.awt.Font.PLAIN, 14 ) );
220         keyText.setSize( new java.awt.Dimension( 130, 20 ) );
221         jLabel2.setText( "Cursor Type:" );
222 
223         scanBut.setText( "Scan" );
224         scanBut.addActionListener( new ActionListener()
225         {
226             @SuppressWarnings("unchecked")
227             public void actionPerformed( ActionEvent e )
228             {
229                 //noinspection unchecked
230                 doScan( ( K ) keyText.getText(), selectedCursorType );
231             }
232         } );
233 
234         doScan( null, DEFAULT_CURSOR );
235     }
236 
237     private String selectedCursorType = DEFAULT_CURSOR;
238 
239     class RadioButtonListener implements ActionListener
240     {
241         public void actionPerformed( ActionEvent e )
242         {
243             if ( e.getActionCommand().equals( DEFAULT_CURSOR ) )
244             {
245                 selectedCursorType = DEFAULT_CURSOR;
246             }
247             else if ( e.getActionCommand().equals( EQUALITY_CURSOR ) )
248             {
249                 selectedCursorType = EQUALITY_CURSOR;
250             }
251             else if ( e.getActionCommand().equals( GREATER_CURSOR ) )
252             {
253                 selectedCursorType = GREATER_CURSOR;
254             }
255             else if ( e.getActionCommand().equals( LESS_CURSOR ) )
256             {
257                 selectedCursorType = LESS_CURSOR;
258             }
259             else if ( e.getActionCommand().equals( REGEX_CURSOR ) )
260             {
261                 selectedCursorType = REGEX_CURSOR;
262             }
263         }
264     }
265 
266 
267     private void closeDialog()
268     {
269         setVisible( false );
270         dispose();
271     }
272 
273 
274     public boolean doScan( K key, String scanType )
275     {
276         if ( key == null && ! scanType.equals( DEFAULT_CURSOR ) )
277         {
278             JOptionPane.showMessageDialog( null, "Cannot use a " + scanType + " scan type with a null key constraint.",
279                 "Missing Key Constraint", JOptionPane.ERROR_MESSAGE );
280             return false;
281         }
282 
283         Object[] cols = new Object[2];
284         Object[] row;
285         cols[0] = "Keys ( Attribute Value )";
286         cols[1] = "Values ( Entry Id )";
287         DefaultTableModel model = new DefaultTableModel( cols, 0 );
288         int count = 0;
289 
290         try
291         {
292             Cursor<IndexEntry<K, O>> list;
293 
294             if ( scanType.equals( EQUALITY_CURSOR ) )
295             {
296                 list = index.forwardCursor( key );
297                 list.beforeFirst();
298                 while ( list.next() )
299                 {
300                     IndexEntry<K,O> rec = list.get();
301                     row = new Object[2];
302                     row[0] = rec.getValue();
303                     row[1] = rec.getId();
304                     model.addRow( row );
305                     count++;
306                 }
307             }
308             else if ( scanType.equals( GREATER_CURSOR ) )
309             {
310                 list = index.forwardCursor();
311                 ForwardIndexEntry<K, O> entry = new ForwardIndexEntry<K, O>();
312                 entry.setValue( key );
313                 list.before( entry );
314                 while ( list.next() )
315                 {
316                     IndexEntry<K,O> rec = list.get();
317                     row = new Object[2];
318                     row[0] = rec.getValue();
319                     row[1] = rec.getId();
320                     model.addRow( row );
321                     count++;
322                 }
323             }
324             else if ( scanType.equals( LESS_CURSOR ) )
325             {
326                 list = index.forwardCursor();
327                 ForwardIndexEntry<K, O> entry = new ForwardIndexEntry<K, O>();
328                 entry.setValue( key );
329                 list.after( entry );
330                 while ( list.previous() )
331                 {
332                     IndexEntry<K,O> rec = list.get();
333                     row = new Object[2];
334                     row[0] = rec.getValue();
335                     row[1] = rec.getId();
336                     model.addRow( row );
337                     count++;
338                 }
339             }
340             else if ( scanType.equals( REGEX_CURSOR ) )
341             {
342 //                Pattern regex = StringTools.getRegex( key );
343 //                int starIndex = key.indexOf( '*' );
344 //
345 //                if ( starIndex > 0 )
346 //                {
347 //                    String prefix = key.substring( 0, starIndex );
348 //
349 //                    if ( log.isDebugEnabled() )
350 //                        log.debug( "Regex prefix = " + prefix );
351 //
352 //                    list = index.listIndices( regex, prefix );
353 //                }
354 //                else
355 //                {
356 //                    list = index.listIndices( regex );
357 //                }
358                 throw new NotImplementedException();
359             }
360             else
361             {
362                 list = index.forwardCursor();
363                 while ( list.next() )
364                 {
365                     IndexEntry<K,O> rec = list.get();
366                     row = new Object[2];
367                     row[0] = rec.getValue();
368                     row[1] = rec.getId();
369                     model.addRow( row );
370                     count++;
371                 }
372             }
373 
374             resultsTbl.setModel( model );
375             resultsPnl.setBorder( BorderFactory.createTitledBorder( BorderFactory.createLineBorder( new Color( 153,
376                 153, 153 ), 1 ), "Scan Results: " + count, TitledBorder.LEADING, TitledBorder.TOP, new Font(
377                 "SansSerif", 0, 14 ), new Color( 60, 60, 60 ) ) );
378 
379             if ( isVisible() )
380             {
381                 validate();
382             }
383         }
384         catch ( Exception e )
385         {
386             String msg = ExceptionUtils.getStackTrace( e );
387 
388             if ( msg.length() > 1024 )
389             {
390                 msg = msg.substring( 0, 1024 ) + "\n. . . TRUNCATED . . .";
391             }
392 
393             msg = "Error while scanning index " + "on attribute " + index.getAttribute() + " using a " + scanType
394                 + " cursor type with a key constraint of '" + key + "':\n" + msg;
395 
396             LOG.error( msg, e );
397             JTextArea area = new JTextArea();
398             area.setText( msg );
399             JOptionPane.showMessageDialog( null, area, "Index Scan Error", JOptionPane.ERROR_MESSAGE );
400             return false;
401         }
402 
403         return true;
404     }
405     
406     
407     @SuppressWarnings("unchecked")
408     public static void show( Index<?,ServerEntry> index )
409     {
410         IndexDialog<?,ServerEntry> dialog = new IndexDialog( index );
411         dialog.setVisible( true );
412     }
413 }