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.xdbm.tools; 021 022 023 import java.awt.Color; 024 import java.awt.Font; 025 import java.awt.Frame; 026 import java.awt.Panel; 027 import java.awt.event.ActionEvent; 028 import java.awt.event.ActionListener; 029 030 import javax.swing.BorderFactory; 031 import javax.swing.BoxLayout; 032 import javax.swing.ButtonGroup; 033 import javax.swing.JButton; 034 import javax.swing.JDialog; 035 import javax.swing.JLabel; 036 import javax.swing.JOptionPane; 037 import javax.swing.JPanel; 038 import javax.swing.JRadioButton; 039 import javax.swing.JScrollPane; 040 import javax.swing.JTabbedPane; 041 import javax.swing.JTable; 042 import javax.swing.JTextArea; 043 import javax.swing.JTextField; 044 import javax.swing.border.TitledBorder; 045 import javax.swing.table.DefaultTableModel; 046 047 import org.apache.directory.server.xdbm.Index; 048 import org.apache.directory.server.xdbm.IndexEntry; 049 import org.apache.directory.server.xdbm.ForwardIndexEntry; 050 import org.apache.directory.server.i18n.I18n; 051 import org.apache.directory.shared.ldap.cursor.Cursor; 052 import org.apache.directory.shared.ldap.entry.ServerEntry; 053 import org.apache.directory.shared.ldap.util.ExceptionUtils; 054 import org.apache.directory.shared.ldap.NotImplementedException; 055 056 import org.slf4j.Logger; 057 import org.slf4j.LoggerFactory; 058 059 060 /** 061 * A dialog showing index values. 062 * 063 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 064 * @version $Rev: 639279 $ 065 */ 066 public class IndexDialog<K, O, ID> extends JDialog 067 { 068 private static final Logger LOG = LoggerFactory.getLogger( IndexDialog.class ); 069 070 private static final long serialVersionUID = 3689917253680445238L; 071 072 public static final String DEFAULT_CURSOR = "Default"; 073 public static final String EQUALITY_CURSOR = "Equality"; 074 public static final String GREATER_CURSOR = "Greater"; 075 public static final String LESS_CURSOR = "Less"; 076 public static final String REGEX_CURSOR = "Regex"; 077 078 private Panel mainPnl = new Panel(); 079 private JTabbedPane tabbedPane = new JTabbedPane(); 080 private JPanel listPnl = new JPanel(); 081 private JPanel cursorPnl = new JPanel(); 082 private JPanel resultsPnl = new JPanel(); 083 private JScrollPane jScrollPane2 = new JScrollPane(); 084 private JTable resultsTbl = new JTable(); 085 private JPanel buttonPnl = new JPanel(); 086 private JButton doneBut = new JButton(); 087 private JLabel jLabel1 = new JLabel(); 088 private JTextField keyText = new JTextField(); 089 private JLabel jLabel2 = new JLabel(); 090 private JButton scanBut = new JButton(); 091 092 private Index<K, O, ID> index = null; 093 094 095 public IndexDialog( Frame parent, boolean modal, Index<K, O, ID> index ) 096 { 097 super( parent, modal ); 098 this.index = index; 099 initGUI(); 100 } 101 102 103 public IndexDialog( Index<K, O, ID> index ) 104 { 105 super(); 106 this.index = index; 107 initGUI(); 108 } 109 110 111 /** 112 * This method is called from within the constructor to initialize the 113 * form. 114 */ 115 private void initGUI() 116 { 117 addWindowListener( new java.awt.event.WindowAdapter() 118 { 119 public void windowClosing( java.awt.event.WindowEvent evt ) 120 { 121 closeDialog(); 122 } 123 } ); 124 125 pack(); 126 setTitle( "Index On Attribute '" + index.getAttribute().getName() + "'" ); 127 setBounds( new java.awt.Rectangle( 0, 0, 512, 471 ) ); 128 getContentPane().add( mainPnl, java.awt.BorderLayout.CENTER ); 129 mainPnl.setLayout( new java.awt.BorderLayout() ); 130 mainPnl.add( tabbedPane, java.awt.BorderLayout.CENTER ); 131 tabbedPane.add( listPnl, "Listing" ); 132 listPnl.setLayout( new java.awt.GridBagLayout() ); 133 134 RadioButtonListener radioListener = new RadioButtonListener(); 135 JRadioButton radioDefault = new JRadioButton( DEFAULT_CURSOR ); 136 radioDefault.setActionCommand( DEFAULT_CURSOR ); 137 radioDefault.setSelected( true ); 138 radioDefault.addActionListener( radioListener ); 139 140 JRadioButton radioEquality = new JRadioButton( EQUALITY_CURSOR ); 141 radioEquality.setActionCommand( EQUALITY_CURSOR ); 142 radioEquality.addActionListener( radioListener ); 143 144 JRadioButton radioGreater = new JRadioButton( GREATER_CURSOR ); 145 radioGreater.setActionCommand( GREATER_CURSOR ); 146 radioGreater.addActionListener( radioListener ); 147 148 JRadioButton radioLess = new JRadioButton( LESS_CURSOR ); 149 radioLess.setActionCommand( LESS_CURSOR ); 150 radioLess.addActionListener( radioListener ); 151 152 JRadioButton radioRegex = new JRadioButton( REGEX_CURSOR ); 153 radioRegex.setActionCommand( REGEX_CURSOR ); 154 radioRegex.addActionListener( radioListener ); 155 156 ButtonGroup group = new ButtonGroup(); 157 group.add( radioDefault ); 158 group.add( radioEquality ); 159 group.add( radioGreater ); 160 group.add( radioLess ); 161 group.add( radioRegex ); 162 163 JPanel radioPanel = new JPanel(); 164 radioPanel.setLayout( new BoxLayout( radioPanel, BoxLayout.X_AXIS ) ); 165 radioPanel.add( radioDefault ); 166 radioPanel.add( radioEquality ); 167 radioPanel.add( radioGreater ); 168 radioPanel.add( radioLess ); 169 radioPanel.add( radioRegex ); 170 171 listPnl.add( cursorPnl, new java.awt.GridBagConstraints( 0, 0, 1, 1, 1.0, 0.15, 172 java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 15, 0, 30, 0 ), 173 0, 0 ) ); 174 listPnl.add( resultsPnl, new java.awt.GridBagConstraints( 0, 1, 1, 1, 1.0, 0.8, 175 java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 0, 0, 0, 0 ), 0, 176 0 ) ); 177 listPnl.add( buttonPnl, new java.awt.GridBagConstraints( 0, 2, 1, 1, 1.0, 0.05, 178 java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 0, 0, 0, 0 ), 0, 179 0 ) ); 180 cursorPnl.setLayout( new java.awt.GridBagLayout() ); 181 cursorPnl.setBorder( javax.swing.BorderFactory.createTitledBorder( javax.swing.BorderFactory.createLineBorder( 182 new java.awt.Color( 153, 153, 153 ), 1 ), "Display Cursor Constraints", 183 javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP, new java.awt.Font( 184 "SansSerif", 0, 14 ), new java.awt.Color( 60, 60, 60 ) ) ); 185 cursorPnl.add( jLabel1, new java.awt.GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, 186 java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE, new java.awt.Insets( 0, 15, 0, 10 ), 0, 187 0 ) ); 188 cursorPnl.add( keyText, new java.awt.GridBagConstraints( 1, 1, 1, 1, 0.4, 0.0, 189 java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 5, 5, 5, 236 ), 0, 190 0 ) ); 191 cursorPnl.add( jLabel2, new java.awt.GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, 192 java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE, new java.awt.Insets( 0, 15, 0, 10 ), 0, 193 0 ) ); 194 cursorPnl.add( radioPanel, 195 new java.awt.GridBagConstraints( 1, 0, 1, 1, 0.4, 0.0, java.awt.GridBagConstraints.WEST, 196 java.awt.GridBagConstraints.NONE, new java.awt.Insets( 5, 5, 5, 0 ), 0, 0 ) ); 197 resultsPnl.setLayout( new java.awt.BorderLayout() ); 198 resultsPnl.setBorder( javax.swing.BorderFactory.createTitledBorder( javax.swing.BorderFactory.createLineBorder( 199 new java.awt.Color( 153, 153, 153 ), 1 ), "Scan Results", javax.swing.border.TitledBorder.LEADING, 200 javax.swing.border.TitledBorder.TOP, new java.awt.Font( "SansSerif", 0, 14 ), new java.awt.Color( 60, 60, 201 60 ) ) ); 202 resultsPnl.add( jScrollPane2, java.awt.BorderLayout.CENTER ); 203 jScrollPane2.getViewport().add( resultsTbl ); 204 buttonPnl.setLayout( new java.awt.FlowLayout( java.awt.FlowLayout.CENTER, 15, 5 ) ); 205 buttonPnl.add( doneBut ); 206 buttonPnl.add( scanBut ); 207 doneBut.setText( "Done" ); 208 doneBut.addActionListener( new ActionListener() 209 { 210 public void actionPerformed( ActionEvent e ) 211 { 212 closeDialog(); 213 } 214 } ); 215 216 jLabel1.setText( "Key Constraint:" ); 217 keyText.setText( "" ); 218 keyText.setMinimumSize( new java.awt.Dimension( 130, 20 ) ); 219 keyText.setPreferredSize( new java.awt.Dimension( 130, 20 ) ); 220 keyText.setMaximumSize( new java.awt.Dimension( 130, 20 ) ); 221 keyText.setFont( new java.awt.Font( "SansSerif", java.awt.Font.PLAIN, 14 ) ); 222 keyText.setSize( new java.awt.Dimension( 130, 20 ) ); 223 jLabel2.setText( "Cursor Type:" ); 224 225 scanBut.setText( "Scan" ); 226 scanBut.addActionListener( new ActionListener() 227 { 228 @SuppressWarnings("unchecked") 229 public void actionPerformed( ActionEvent e ) 230 { 231 //noinspection unchecked 232 doScan( ( K ) keyText.getText(), selectedCursorType ); 233 } 234 } ); 235 236 doScan( null, DEFAULT_CURSOR ); 237 } 238 239 private String selectedCursorType = DEFAULT_CURSOR; 240 241 class RadioButtonListener implements ActionListener 242 { 243 public void actionPerformed( ActionEvent e ) 244 { 245 if ( e.getActionCommand().equals( DEFAULT_CURSOR ) ) 246 { 247 selectedCursorType = DEFAULT_CURSOR; 248 } 249 else if ( e.getActionCommand().equals( EQUALITY_CURSOR ) ) 250 { 251 selectedCursorType = EQUALITY_CURSOR; 252 } 253 else if ( e.getActionCommand().equals( GREATER_CURSOR ) ) 254 { 255 selectedCursorType = GREATER_CURSOR; 256 } 257 else if ( e.getActionCommand().equals( LESS_CURSOR ) ) 258 { 259 selectedCursorType = LESS_CURSOR; 260 } 261 else if ( e.getActionCommand().equals( REGEX_CURSOR ) ) 262 { 263 selectedCursorType = REGEX_CURSOR; 264 } 265 } 266 } 267 268 269 private void closeDialog() 270 { 271 setVisible( false ); 272 dispose(); 273 } 274 275 276 public boolean doScan( K key, String scanType ) 277 { 278 if ( key == null && !scanType.equals( DEFAULT_CURSOR ) ) 279 { 280 JOptionPane.showMessageDialog( null, "Cannot use a " + scanType + " scan type with a null key constraint.", 281 "Missing Key Constraint", JOptionPane.ERROR_MESSAGE ); 282 return false; 283 } 284 285 Object[] cols = new Object[2]; 286 Object[] row; 287 cols[0] = "Keys ( Attribute Value )"; 288 cols[1] = "Values ( Entry Id )"; 289 DefaultTableModel model = new DefaultTableModel( cols, 0 ); 290 int count = 0; 291 292 try 293 { 294 Cursor<IndexEntry<K, O, ID>> list; 295 296 if ( scanType.equals( EQUALITY_CURSOR ) ) 297 { 298 list = index.forwardCursor( key ); 299 list.beforeFirst(); 300 while ( list.next() ) 301 { 302 IndexEntry<K, O, ID> rec = list.get(); 303 row = new Object[2]; 304 row[0] = rec.getValue(); 305 row[1] = rec.getId(); 306 model.addRow( row ); 307 count++; 308 } 309 } 310 else if ( scanType.equals( GREATER_CURSOR ) ) 311 { 312 list = index.forwardCursor(); 313 ForwardIndexEntry<K, O, ID> entry = new ForwardIndexEntry<K, O, ID>(); 314 entry.setValue( key ); 315 list.before( entry ); 316 while ( list.next() ) 317 { 318 IndexEntry<K, O, ID> rec = list.get(); 319 row = new Object[2]; 320 row[0] = rec.getValue(); 321 row[1] = rec.getId(); 322 model.addRow( row ); 323 count++; 324 } 325 } 326 else if ( scanType.equals( LESS_CURSOR ) ) 327 { 328 list = index.forwardCursor(); 329 ForwardIndexEntry<K, O, ID> entry = new ForwardIndexEntry<K, O, ID>(); 330 entry.setValue( key ); 331 list.after( entry ); 332 while ( list.previous() ) 333 { 334 IndexEntry<K, O, ID> rec = list.get(); 335 row = new Object[2]; 336 row[0] = rec.getValue(); 337 row[1] = rec.getId(); 338 model.addRow( row ); 339 count++; 340 } 341 } 342 else if ( scanType.equals( REGEX_CURSOR ) ) 343 { 344 // Pattern regex = StringTools.getRegex( key ); 345 // int starIndex = key.indexOf( '*' ); 346 // 347 // if ( starIndex > 0 ) 348 // { 349 // String prefix = key.substring( 0, starIndex ); 350 // 351 // if ( log.isDebugEnabled() ) 352 // log.debug( "Regex prefix = " + prefix ); 353 // 354 // list = index.listIndices( regex, prefix ); 355 // } 356 // else 357 // { 358 // list = index.listIndices( regex ); 359 // } 360 throw new NotImplementedException(); 361 } 362 else 363 { 364 list = index.forwardCursor(); 365 while ( list.next() ) 366 { 367 IndexEntry<K, O, ID> rec = list.get(); 368 row = new Object[2]; 369 row[0] = rec.getValue(); 370 row[1] = rec.getId(); 371 model.addRow( row ); 372 count++; 373 } 374 } 375 376 resultsTbl.setModel( model ); 377 resultsPnl.setBorder( BorderFactory.createTitledBorder( BorderFactory.createLineBorder( new Color( 153, 378 153, 153 ), 1 ), "Scan Results: " + count, TitledBorder.LEADING, TitledBorder.TOP, new Font( 379 "SansSerif", 0, 14 ), new Color( 60, 60, 60 ) ) ); 380 381 if ( isVisible() ) 382 { 383 validate(); 384 } 385 } 386 catch ( Exception e ) 387 { 388 String msg = ExceptionUtils.getStackTrace( e ); 389 390 if ( msg.length() > 1024 ) 391 { 392 msg = msg.substring( 0, 1024 ) + "\n. . . TRUNCATED . . ."; 393 } 394 395 msg = I18n.err( I18n.ERR_183, index.getAttribute(), scanType, key, msg ); 396 397 LOG.error( msg, e ); 398 JTextArea area = new JTextArea(); 399 area.setText( msg ); 400 JOptionPane.showMessageDialog( null, area, "Index Scan Error", JOptionPane.ERROR_MESSAGE ); 401 return false; 402 } 403 404 return true; 405 } 406 407 408 @SuppressWarnings("unchecked") 409 public static void show( Index<?, ServerEntry, Long> index ) 410 { 411 IndexDialog<?, ServerEntry, Long> dialog = new IndexDialog( index ); 412 dialog.setVisible( true ); 413 } 414 }