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.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.i18n.I18n; 048 import org.apache.directory.server.xdbm.IndexEntry; 049 import org.apache.directory.server.xdbm.ForwardIndexEntry; 050 import org.apache.directory.server.xdbm.Index; 051 import org.apache.directory.shared.ldap.cursor.Cursor; 052 import org.apache.directory.shared.ldap.util.ExceptionUtils; 053 import org.apache.directory.shared.ldap.NotImplementedException; 054 055 import org.slf4j.Logger; 056 import org.slf4j.LoggerFactory; 057 058 059 /** 060 * A dialog showing index values. 061 * 062 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 063 * @version $Rev: 917312 $ 064 */ 065 public class IndexDialog<K, O, ID> extends JDialog 066 { 067 private static final Logger LOG = LoggerFactory.getLogger( IndexDialog.class ); 068 069 private static final long serialVersionUID = 3689917253680445238L; 070 071 public static final String DEFAULT_CURSOR = "Default"; 072 public static final String EQUALITY_CURSOR = "Equality"; 073 public static final String GREATER_CURSOR = "Greater"; 074 public static final String LESS_CURSOR = "Less"; 075 public static final String REGEX_CURSOR = "Regex"; 076 077 private Panel mainPnl = new Panel(); 078 private JTabbedPane tabbedPane = new JTabbedPane(); 079 private JPanel listPnl = new JPanel(); 080 private JPanel cursorPnl = new JPanel(); 081 private JPanel resultsPnl = new JPanel(); 082 private JScrollPane jScrollPane2 = new JScrollPane(); 083 private JTable resultsTbl = new JTable(); 084 private JPanel buttonPnl = new JPanel(); 085 private JButton doneBut = new JButton(); 086 private JLabel jLabel1 = new JLabel(); 087 private JTextField keyText = new JTextField(); 088 private JLabel jLabel2 = new JLabel(); 089 private JButton scanBut = new JButton(); 090 091 private Index<K, O, ID> index = null; 092 093 094 public IndexDialog( Frame parent, boolean modal, Index<K, O, ID> index ) 095 { 096 super( parent, modal ); 097 this.index = index; 098 initGUI(); 099 } 100 101 102 public IndexDialog( Index<K, O, ID> index ) 103 { 104 super(); 105 this.index = index; 106 initGUI(); 107 } 108 109 110 /** 111 * This method is called from within the constructor to initialize the 112 * form. 113 */ 114 private void initGUI() 115 { 116 addWindowListener( new java.awt.event.WindowAdapter() 117 { 118 public void windowClosing( java.awt.event.WindowEvent evt ) 119 { 120 closeDialog(); 121 } 122 } ); 123 124 pack(); 125 setTitle( "Index On Attribute '" + index.getAttribute().getName() + "'" ); 126 setBounds( new java.awt.Rectangle( 0, 0, 512, 471 ) ); 127 getContentPane().add( mainPnl, java.awt.BorderLayout.CENTER ); 128 mainPnl.setLayout( new java.awt.BorderLayout() ); 129 mainPnl.add( tabbedPane, java.awt.BorderLayout.CENTER ); 130 tabbedPane.add( listPnl, "Listing" ); 131 listPnl.setLayout( new java.awt.GridBagLayout() ); 132 133 RadioButtonListener radioListener = new RadioButtonListener(); 134 JRadioButton radioDefault = new JRadioButton( DEFAULT_CURSOR ); 135 radioDefault.setActionCommand( DEFAULT_CURSOR ); 136 radioDefault.setSelected( true ); 137 radioDefault.addActionListener( radioListener ); 138 139 JRadioButton radioEquality = new JRadioButton( EQUALITY_CURSOR ); 140 radioEquality.setActionCommand( EQUALITY_CURSOR ); 141 radioEquality.addActionListener( radioListener ); 142 143 JRadioButton radioGreater = new JRadioButton( GREATER_CURSOR ); 144 radioGreater.setActionCommand( GREATER_CURSOR ); 145 radioGreater.addActionListener( radioListener ); 146 147 JRadioButton radioLess = new JRadioButton( LESS_CURSOR ); 148 radioLess.setActionCommand( LESS_CURSOR ); 149 radioLess.addActionListener( radioListener ); 150 151 JRadioButton radioRegex = new JRadioButton( REGEX_CURSOR ); 152 radioRegex.setActionCommand( REGEX_CURSOR ); 153 radioRegex.addActionListener( radioListener ); 154 155 ButtonGroup group = new ButtonGroup(); 156 group.add( radioDefault ); 157 group.add( radioEquality ); 158 group.add( radioGreater ); 159 group.add( radioLess ); 160 group.add( radioRegex ); 161 162 JPanel radioPanel = new JPanel(); 163 radioPanel.setLayout( new BoxLayout( radioPanel, BoxLayout.X_AXIS ) ); 164 radioPanel.add( radioDefault ); 165 radioPanel.add( radioEquality ); 166 radioPanel.add( radioGreater ); 167 radioPanel.add( radioLess ); 168 radioPanel.add( radioRegex ); 169 170 listPnl.add( cursorPnl, new java.awt.GridBagConstraints( 0, 0, 1, 1, 1.0, 0.15, 171 java.awt.GridBagConstraints.NORTH, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 15, 0, 30, 0 ), 172 0, 0 ) ); 173 listPnl.add( resultsPnl, new java.awt.GridBagConstraints( 0, 1, 1, 1, 1.0, 0.8, 174 java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 0, 0, 0, 0 ), 0, 175 0 ) ); 176 listPnl.add( buttonPnl, new java.awt.GridBagConstraints( 0, 2, 1, 1, 1.0, 0.05, 177 java.awt.GridBagConstraints.CENTER, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 0, 0, 0, 0 ), 0, 178 0 ) ); 179 cursorPnl.setLayout( new java.awt.GridBagLayout() ); 180 cursorPnl.setBorder( javax.swing.BorderFactory.createTitledBorder( javax.swing.BorderFactory.createLineBorder( 181 new java.awt.Color( 153, 153, 153 ), 1 ), "Display Cursor Constraints", 182 javax.swing.border.TitledBorder.LEADING, javax.swing.border.TitledBorder.TOP, new java.awt.Font( 183 "SansSerif", 0, 14 ), new java.awt.Color( 60, 60, 60 ) ) ); 184 cursorPnl.add( jLabel1, new java.awt.GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, 185 java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE, new java.awt.Insets( 0, 15, 0, 10 ), 0, 186 0 ) ); 187 cursorPnl.add( keyText, new java.awt.GridBagConstraints( 1, 1, 1, 1, 0.4, 0.0, 188 java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.BOTH, new java.awt.Insets( 5, 5, 5, 236 ), 0, 189 0 ) ); 190 cursorPnl.add( jLabel2, new java.awt.GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, 191 java.awt.GridBagConstraints.WEST, java.awt.GridBagConstraints.NONE, new java.awt.Insets( 0, 15, 0, 10 ), 0, 192 0 ) ); 193 cursorPnl.add( radioPanel, 194 new java.awt.GridBagConstraints( 1, 0, 1, 1, 0.4, 0.0, java.awt.GridBagConstraints.WEST, 195 java.awt.GridBagConstraints.NONE, new java.awt.Insets( 5, 5, 5, 0 ), 0, 0 ) ); 196 resultsPnl.setLayout( new java.awt.BorderLayout() ); 197 resultsPnl.setBorder( javax.swing.BorderFactory.createTitledBorder( javax.swing.BorderFactory.createLineBorder( 198 new java.awt.Color( 153, 153, 153 ), 1 ), "Scan Results", javax.swing.border.TitledBorder.LEADING, 199 javax.swing.border.TitledBorder.TOP, new java.awt.Font( "SansSerif", 0, 14 ), new java.awt.Color( 60, 60, 200 60 ) ) ); 201 resultsPnl.add( jScrollPane2, java.awt.BorderLayout.CENTER ); 202 jScrollPane2.getViewport().add( resultsTbl ); 203 buttonPnl.setLayout( new java.awt.FlowLayout( java.awt.FlowLayout.CENTER, 15, 5 ) ); 204 buttonPnl.add( doneBut ); 205 buttonPnl.add( scanBut ); 206 doneBut.setText( "Done" ); 207 doneBut.addActionListener( new ActionListener() 208 { 209 public void actionPerformed( ActionEvent e ) 210 { 211 closeDialog(); 212 } 213 } ); 214 215 jLabel1.setText( "Key Constraint:" ); 216 keyText.setText( "" ); 217 keyText.setMinimumSize( new java.awt.Dimension( 130, 20 ) ); 218 keyText.setPreferredSize( new java.awt.Dimension( 130, 20 ) ); 219 keyText.setMaximumSize( new java.awt.Dimension( 130, 20 ) ); 220 keyText.setFont( new java.awt.Font( "SansSerif", java.awt.Font.PLAIN, 14 ) ); 221 keyText.setSize( new java.awt.Dimension( 130, 20 ) ); 222 jLabel2.setText( "Cursor Type:" ); 223 224 scanBut.setText( "Scan" ); 225 scanBut.addActionListener( new ActionListener() 226 { 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, ID>> 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, ID> 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, ID> entry = new ForwardIndexEntry<K, O, ID>(); 312 entry.setValue( key ); 313 list.before( entry ); 314 while ( list.next() ) 315 { 316 IndexEntry<K, O, ID> 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, ID> entry = new ForwardIndexEntry<K, O, ID>(); 328 entry.setValue( key ); 329 list.after( entry ); 330 while ( list.previous() ) 331 { 332 IndexEntry<K, O, ID> 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, ID> 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 = I18n.err( I18n.ERR_183, index.getAttribute(), scanType, key, msg ); 394 395 LOG.error( msg, e ); 396 JTextArea area = new JTextArea(); 397 area.setText( msg ); 398 JOptionPane.showMessageDialog( null, area, "Index Scan Error", JOptionPane.ERROR_MESSAGE ); 399 return false; 400 } 401 402 return true; 403 } 404 405 406 public static void show( Index index ) 407 { 408 //noinspection unchecked 409 IndexDialog dialog = new IndexDialog( index ); 410 dialog.setVisible( true ); 411 } 412 }