blob: bdfb6d8a26967f929698b6dc96e2ff8fc1c89b4e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.studio.ldapbrowser.common.widgets.browser;
import java.util.Arrays;
import java.util.Collection;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.studio.common.ui.HistoryUtils;
import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
import org.apache.directory.studio.connection.ui.widgets.ExtendedContentAssistCommandAdapter;
import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
import org.apache.directory.studio.ldapbrowser.common.actions.BrowserSelectionUtils;
import org.apache.directory.studio.ldapbrowser.common.widgets.ListContentProposalProvider;
import org.apache.directory.studio.ldapbrowser.core.jobs.SearchRunnable;
import org.apache.directory.studio.ldapbrowser.core.jobs.StudioBrowserJob;
import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
import org.apache.directory.studio.ldapbrowser.core.model.IQuickSearch;
import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
import org.apache.directory.studio.ldapbrowser.core.model.impl.QuickSearch;
import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
/**
* The BrowserQuickSearchWidget implements an instant search
* for the browser widget.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class BrowserQuickSearchWidget
{
/** The Constant VALUE_HISTORY_DIALOGSETTING_KEY. */
public static final String VALUE_HISTORY_DIALOGSETTING_KEY = BrowserQuickSearchWidget.class.getName()
+ ".valueHistory"; //$NON-NLS-1$
/** The Constant ATTRIBUTE_HISTORY_DIALOGSETTING_KEY. */
public static final String ATTRIBUTE_HISTORY_DIALOGSETTING_KEY = BrowserQuickSearchWidget.class.getName()
+ ".attributeHistory"; //$NON-NLS-1$
/** An empty string array */
private static final String[] EMPTY = new String[0];
/** The browser widget. */
private BrowserWidget browserWidget;
/** The parent, used to create the composite. */
private Composite parent;
/** The outer composite. */
private Composite composite;
/** The inner composite, it is created/destroyed when showing/hiding the quick search. */
private Composite innerComposite;
/** The quick search attribute combo. */
private Combo quickSearchAttributeCombo;
/** The quick search attribute proposal provider. */
private ListContentProposalProvider quickSearchAttributePP;
/** The quick search operator combo. */
private Combo quickSearchOperatorCombo;
/** The quick search value combo. */
private Combo quickSearchValueCombo;
/** The quick search value proposal provider. */
private ListContentProposalProvider quickSearchValuePP;
/** The quick search scope button. */
private Button quickSearchScopeButton;
/** The quick search run button. */
private Button quickSearchRunButton;
/** Listener that listens for selections of connections */
private ISelectionChangedListener selectionListener = new ISelectionChangedListener()
{
/**
* {@inheritDoc}
*
* This implementation sets the input when another connection was selected.
*/
public void selectionChanged( SelectionChangedEvent event )
{
setEnabled( getSelectedEntry() != null );
}
};
/**
* Creates a new instance of BrowserQuickSearchWidget.
*
* @param browserWidget the browser widget
*/
public BrowserQuickSearchWidget( BrowserWidget browserWidget )
{
this.browserWidget = browserWidget;
if ( HistoryUtils.load( BrowserCommonActivator.getDefault().getDialogSettings(),
ATTRIBUTE_HISTORY_DIALOGSETTING_KEY ).length == 0 )
{
BrowserCommonActivator.getDefault().getDialogSettings().put( ATTRIBUTE_HISTORY_DIALOGSETTING_KEY,
new String[]
{ "cn", //$NON-NLS-1$
"sn", //$NON-NLS-1$
"givenName", //$NON-NLS-1$
"mail", //$NON-NLS-1$
"uid", //$NON-NLS-1$
"description", //$NON-NLS-1$
"o", //$NON-NLS-1$
"ou", //$NON-NLS-1$
"member" //$NON-NLS-1$
} );
}
}
/**
* Creates the outer composite.
*
* @param parent the parent
*/
public void createComposite( Composite parent )
{
this.parent = parent;
composite = BaseWidgetUtils.createColumnContainer( parent, 1, 1 );
GridLayout gl = new GridLayout();
gl.marginHeight = 2;
gl.marginWidth = 2;
composite.setLayout( gl );
// Setting the default width and height of the composite to 0
GridData compositeGridData = new GridData( SWT.NONE, SWT.NONE, false, false );
compositeGridData.heightHint = 0;
compositeGridData.widthHint = 0;
composite.setLayoutData( compositeGridData );
innerComposite = null;
}
/**
* Creates the inner composite with its input fields.
*/
private void create()
{
this.browserWidget.getViewer().addPostSelectionChangedListener( selectionListener );
IDialogSettings dialogSettings = BrowserCommonActivator.getDefault().getDialogSettings();
// Reseting the layout of the composite to be displayed correctly
GridData compositeGridData = new GridData( SWT.FILL, SWT.NONE, true, false );
composite.setLayoutData( compositeGridData );
innerComposite = BaseWidgetUtils.createColumnContainer( composite, 5, 1 );
String[] attributes = HistoryUtils.load( dialogSettings, ATTRIBUTE_HISTORY_DIALOGSETTING_KEY );
quickSearchAttributeCombo = BaseWidgetUtils.createCombo( innerComposite, attributes, -1, 1 );
quickSearchAttributePP = new ListContentProposalProvider( attributes );
new ExtendedContentAssistCommandAdapter( quickSearchAttributeCombo, new ComboContentAdapter(),
quickSearchAttributePP, null, null, true );
quickSearchAttributeCombo.addModifyListener( new ModifyListener()
{
public void modifyText( ModifyEvent e )
{
quickSearchRunButton.setEnabled( !"".equals( quickSearchAttributeCombo.getText() ) ); //$NON-NLS-1$
}
} );
quickSearchAttributeCombo.addSelectionListener( new SelectionAdapter()
{
public void widgetDefaultSelected( SelectionEvent e )
{
performSearch();
}
} );
GridData gd = new GridData( GridData.FILL_HORIZONTAL );
gd.widthHint = 50;
quickSearchAttributeCombo.setLayoutData( gd );
String[] operators = new String[]
{ "=", "!=", "<=", ">=", "~=" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
quickSearchOperatorCombo = BaseWidgetUtils.createReadonlyCombo( innerComposite, operators, 0, 1 );
GridData data = new GridData();
quickSearchOperatorCombo.setLayoutData( data );
String[] values = HistoryUtils.load( dialogSettings, VALUE_HISTORY_DIALOGSETTING_KEY );
quickSearchValueCombo = BaseWidgetUtils.createCombo( innerComposite, values, -1, 1 );
quickSearchValuePP = new ListContentProposalProvider( values );
new ExtendedContentAssistCommandAdapter( quickSearchValueCombo, new ComboContentAdapter(), quickSearchValuePP,
null, null, true );
quickSearchValueCombo.addSelectionListener( new SelectionAdapter()
{
public void widgetDefaultSelected( SelectionEvent e )
{
performSearch();
}
} );
gd = new GridData( GridData.FILL_HORIZONTAL );
gd.widthHint = 50;
quickSearchValueCombo.setLayoutData( gd );
quickSearchScopeButton = new Button( innerComposite, SWT.TOGGLE );
quickSearchScopeButton.setToolTipText( Messages.getString( "BrowserQuickSearchWidget.ScopeOneLevelToolTip" ) ); //$NON-NLS-1$
quickSearchScopeButton.setImage( BrowserCommonActivator.getDefault().getImage(
BrowserCommonConstants.IMG_SUBTREE ) );
quickSearchScopeButton.setSelection( BrowserCommonActivator.getDefault().getPreferenceStore()
.getBoolean( BrowserCommonConstants.PREFERENCE_BROWSER_QUICK_SEARCH_SUBTREE_SCOPE ) );
quickSearchScopeButton.addSelectionListener( new SelectionAdapter()
{
public void widgetSelected( SelectionEvent e )
{
String one = Messages.getString( "BrowserQuickSearchWidget.ScopeOneLevelToolTip" ); //$NON-NLS-1$
String sub = Messages.getString( "BrowserQuickSearchWidget.ScopeSubtreeToolTip" ); //$NON-NLS-1$
boolean selected = quickSearchScopeButton.getSelection();
quickSearchScopeButton.setToolTipText( selected ? sub : one );
BrowserCommonActivator.getDefault().getPreferenceStore()
.setValue( BrowserCommonConstants.PREFERENCE_BROWSER_QUICK_SEARCH_SUBTREE_SCOPE, selected );
}
} );
quickSearchRunButton = new Button( innerComposite, SWT.PUSH );
quickSearchRunButton.setToolTipText( Messages.getString( "BrowserQuickSearchWidget.RunQuickSearch" ) ); //$NON-NLS-1$
quickSearchRunButton.setImage( BrowserCommonActivator.getDefault().getImage(
BrowserCommonConstants.IMG_QUICKSEARCH ) );
quickSearchRunButton.addSelectionListener( new SelectionAdapter()
{
public void widgetSelected( SelectionEvent e )
{
performSearch();
}
} );
setEnabled( getSelectedEntry() != null );
composite.layout( true, true );
parent.layout( true, true );
}
private void performSearch()
{
if ( !quickSearchRunButton.isEnabled() )
{
return;
}
IEntry entry = getSelectedEntry();
if ( entry == null )
{
return;
}
IDialogSettings dialogSettings = BrowserCommonActivator.getDefault().getDialogSettings();
HistoryUtils.save( dialogSettings, ATTRIBUTE_HISTORY_DIALOGSETTING_KEY, quickSearchAttributeCombo.getText() );
String[] attributes = HistoryUtils.load( dialogSettings, ATTRIBUTE_HISTORY_DIALOGSETTING_KEY );
quickSearchAttributeCombo.setItems( attributes );
quickSearchAttributeCombo.select( 0 );
HistoryUtils.save( dialogSettings, VALUE_HISTORY_DIALOGSETTING_KEY, quickSearchValueCombo.getText() );
String[] values = HistoryUtils.load( dialogSettings, VALUE_HISTORY_DIALOGSETTING_KEY );
quickSearchValueCombo.setItems( values );
quickSearchValueCombo.select( 0 );
quickSearchValuePP.setProposals( Arrays.asList( values ) );
IBrowserConnection conn = entry.getBrowserConnection();
QuickSearch quickSearch = new QuickSearch( entry, conn );
quickSearch.getSearchParameter().setScope(
quickSearchScopeButton.getSelection() ? SearchScope.SUBTREE : SearchScope.ONELEVEL );
StringBuffer filter = new StringBuffer();
filter.append( "(" ); //$NON-NLS-1$
if ( "!=".equals( quickSearchOperatorCombo.getText() ) ) //$NON-NLS-1$
{
filter.append( "!(" ); //$NON-NLS-1$
}
filter.append( quickSearchAttributeCombo.getText() );
filter
.append( Messages.getString( "BrowserQuickSearchWidget.9" ).equals( quickSearchOperatorCombo.getText() ) ? "=" : quickSearchOperatorCombo.getText() ); //$NON-NLS-1$ //$NON-NLS-2$
// only escape '\', '(', ')', and '\u0000'
// don't escape '*' to allow substring search
String value = quickSearchValueCombo.getText();
value = value.replaceAll( "\\\\", "\\\\5c" ); //$NON-NLS-1$ //$NON-NLS-2$
value = value.replaceAll( "\u0000", "\\\\00" ); //$NON-NLS-1$ //$NON-NLS-2$
value = value.replaceAll( "\\(", "\\\\28" ); //$NON-NLS-1$ //$NON-NLS-2$
value = value.replaceAll( "\\)", "\\\\29" ); //$NON-NLS-1$ //$NON-NLS-2$
filter.append( value );
if ( "!=".equals( quickSearchOperatorCombo.getText() ) ) //$NON-NLS-1$
{
filter.append( ")" ); //$NON-NLS-1$
}
filter.append( ")" ); //$NON-NLS-1$
quickSearch.getSearchParameter().setFilter( filter.toString() );
// set new quick search
conn.setQuickSearch( quickSearch );
// execute quick search
new StudioBrowserJob( new SearchRunnable( new ISearch[]
{ quickSearch } ) ).execute();
}
private IEntry getSelectedEntry()
{
ISelection selection = browserWidget.getViewer().getSelection();
IEntry[] entries = BrowserSelectionUtils.getEntries( selection );
ISearch[] searches = BrowserSelectionUtils.getSearches( selection );
if ( entries != null && entries.length == 1 )
{
IEntry entry = entries[0];
return entry;
}
else if ( searches != null && searches.length == 1 && ( searches[0] instanceof IQuickSearch ) )
{
IQuickSearch quickSearch = ( IQuickSearch ) searches[0];
IEntry entry = quickSearch.getSearchBaseEntry();
return entry;
}
else
{
return null;
}
}
/**
* Destroys the inner widget.
*/
private void destroy()
{
browserWidget.getViewer().removePostSelectionChangedListener( selectionListener );
// Reseting the layout of the composite with a width and height set to 0
GridData compositeGridData = new GridData( SWT.NONE, SWT.NONE, false, false );
compositeGridData.heightHint = 0;
compositeGridData.widthHint = 0;
composite.setLayoutData( compositeGridData );
innerComposite.dispose();
innerComposite = null;
composite.layout( true, true );
parent.layout( true, true );
}
/**
* Disposes this widget.
*/
public void dispose()
{
if ( browserWidget != null )
{
quickSearchAttributeCombo = null;
quickSearchOperatorCombo = null;
quickSearchValueCombo = null;
quickSearchRunButton = null;
innerComposite = null;
composite.dispose();
composite = null;
parent = null;
browserWidget = null;
}
}
/**
* Enables or disables this quick search widget.
*
* @param enabled true to enable this quick search widget, false to disable it
*/
private void setEnabled( boolean enabled )
{
if ( composite != null && !composite.isDisposed() )
{
composite.setEnabled( enabled );
}
if ( innerComposite != null && !innerComposite.isDisposed() )
{
innerComposite.setEnabled( enabled );
quickSearchAttributeCombo.setEnabled( enabled );
quickSearchOperatorCombo.setEnabled( enabled );
quickSearchValueCombo.setEnabled( enabled );
quickSearchScopeButton.setEnabled( enabled );
quickSearchRunButton.setEnabled( enabled && !"".equals( quickSearchAttributeCombo.getText() ) ); //$NON-NLS-1$
if ( !enabled )
{
quickSearchAttributeCombo.setToolTipText( null );
quickSearchOperatorCombo.setToolTipText( null );
quickSearchValueCombo.setToolTipText( null );
parent.setToolTipText( Messages.getString( "BrowserQuickSearchWidget.DisabledToolTipText" ) ); //$NON-NLS-1$
}
else
{
quickSearchAttributeCombo.setToolTipText( Messages
.getString( "BrowserQuickSearchWidget.SearchAttribute" ) ); //$NON-NLS-1$
quickSearchOperatorCombo
.setToolTipText( Messages.getString( "BrowserQuickSearchWidget.SearchOperator" ) ); //$NON-NLS-1$
quickSearchValueCombo.setToolTipText( Messages.getString( "BrowserQuickSearchWidget.SearchValue" ) ); //$NON-NLS-1$
parent.setToolTipText( null );
}
}
}
/**
* Activates or deactivates this quick search widget.
*
* @param visible true to create this quick search widget, false to destroy it
*/
public void setActive( boolean visible )
{
if ( visible && innerComposite == null && composite != null )
{
create();
Object input = browserWidget.getViewer().getInput();
if ( input instanceof IBrowserConnection )
{
setInput( ( IBrowserConnection ) input );
}
else if ( input instanceof IEntry[] )
{
setInput( ( ( IEntry[] ) input )[0].getBrowserConnection() );
}
quickSearchAttributeCombo.setFocus();
}
else if ( !visible && innerComposite != null && composite != null )
{
destroy();
browserWidget.getViewer().getTree().setFocus();
}
}
/**
* Sets the input.
*
* @param connection the new input
*/
public void setInput( IBrowserConnection connection )
{
if ( innerComposite != null && !innerComposite.isDisposed() )
{
String[] atdNames;
if ( connection != null )
{
Collection<AttributeType> atds = connection.getSchema().getAttributeTypeDescriptions();
atdNames = SchemaUtils.getNames( atds ).toArray( EMPTY );
}
else
{
atdNames = EMPTY;
setEnabled( false );
}
quickSearchAttributePP.setProposals( Arrays.asList( atdNames ) );
}
}
}