| /* |
| * 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; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| |
| import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; |
| import org.apache.directory.api.ldap.model.name.Ava; |
| import org.apache.directory.api.ldap.model.name.Dn; |
| import org.apache.directory.api.ldap.model.name.Rdn; |
| import org.apache.directory.studio.common.ui.widgets.AbstractWidget; |
| import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils; |
| import org.apache.directory.studio.connection.core.DnUtils; |
| import org.apache.directory.studio.connection.ui.widgets.ExtendedContentAssistCommandAdapter; |
| import org.apache.directory.studio.ldapbrowser.common.widgets.search.EntryWidget; |
| import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection; |
| import org.eclipse.jface.fieldassist.ComboContentAdapter; |
| import org.eclipse.jface.fieldassist.ContentProposalAdapter; |
| 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.events.SelectionListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| |
| |
| /** |
| * The DnBuilderWidget provides input elements to select a parent Dn |
| * and to build a (multivalued) Rdn. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public class DnBuilderWidget extends AbstractWidget implements ModifyListener |
| { |
| |
| /** The attribute names that could be selected from drop-down list. */ |
| private String[] attributeNames; |
| |
| /** True if the Rdn input elements should be shown. */ |
| private boolean showRDN; |
| |
| /** True if the parent Dn input elements should be shown. */ |
| private boolean showParent; |
| |
| /** The shell. */ |
| private Shell shell; |
| |
| /** The selected parent Dn. */ |
| private Dn parentDn; |
| |
| /** The entry widget label. */ |
| private Label parentEntryLabel; |
| |
| /** The entry widget to enter/select the parent Dn. */ |
| private EntryWidget parentEntryWidget; |
| |
| /** The Rdn label */ |
| private Label rdnLabel; |
| |
| /** The composite that contains the RdnLines. */ |
| private Composite rdnComposite; |
| |
| /** The resulting Rdn. */ |
| private Rdn rdn; |
| |
| /** The list of RdnLines. */ |
| private ArrayList<RdnLine> rdnLineList; |
| |
| /** The preview label. */ |
| private Label previewLabel; |
| |
| /** The preview text. */ |
| private Text previewText; |
| |
| // Listeners |
| private SelectionListener rdnAddButtonSelectionListener = new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected( SelectionEvent e ) |
| { |
| int index = rdnLineList.size(); |
| for ( int i = 0; i < rdnLineList.size(); i++ ) |
| { |
| RdnLine rdnLine = rdnLineList.get( i ); |
| if ( rdnLine.rdnAddButton == e.widget ) |
| { |
| index = i + 1; |
| } |
| } |
| addRdnLine( rdnComposite, index ); |
| |
| validate(); |
| } |
| }; |
| |
| private SelectionListener rdnDeleteButtonSelectionListener = new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected( SelectionEvent e ) |
| { |
| int index = 0; |
| for ( int i = 0; i < rdnLineList.size(); i++ ) |
| { |
| RdnLine rdnLine = rdnLineList.get( i ); |
| if ( rdnLine.rdnDeleteButton == e.widget ) |
| { |
| index = i; |
| } |
| } |
| deleteRdnLine( rdnComposite, index ); |
| |
| validate(); |
| } |
| }; |
| |
| |
| /** |
| * Creates a new instance of DnBuilderWidget. |
| * |
| * @param showParent true if the parent Dn input elements should be shown |
| * @param showRDN true if the Rdn input elements should be shown |
| */ |
| public DnBuilderWidget( boolean showRDN, boolean showParent ) |
| { |
| this.showRDN = showRDN; |
| this.showParent = showParent; |
| } |
| |
| |
| /** |
| * Disposes this widget. |
| */ |
| public void dispose() |
| { |
| } |
| |
| |
| /** |
| * Sets the input. |
| * |
| * @param rdn the initial Rdn |
| * @param attributeNames the attribute names that could be selected from drop-down list |
| * @param browserConnection the connection |
| * @param parentDn the initial parent Dn |
| */ |
| public void setInput( IBrowserConnection browserConnection, String[] attributeNames, Rdn rdn, Dn parentDn ) |
| { |
| this.attributeNames = attributeNames; |
| Rdn currentRdn = rdn; |
| Dn currentParentDn = parentDn; |
| |
| if ( showRDN ) |
| { |
| for ( int i = 0; i < rdnLineList.size(); i++ ) |
| { |
| RdnLine rdnLine = rdnLineList.get( i ); |
| String oldName = rdnLine.rdnTypeCombo.getText(); |
| rdnLine.rdnTypeCombo.setItems( attributeNames ); |
| rdnLine.rdnNameCPA.setContentProposalProvider( new ListContentProposalProvider( attributeNames ) ); |
| if ( Arrays.asList( rdnLine.rdnTypeCombo.getItems() ).contains( oldName ) ) |
| { |
| rdnLine.rdnTypeCombo.setText( oldName ); |
| } |
| } |
| } |
| |
| if ( showRDN ) |
| { |
| while ( !rdnLineList.isEmpty() ) |
| { |
| deleteRdnLine( rdnComposite, 0 ); |
| } |
| if ( currentRdn == null || currentRdn.size() == 0 ) |
| { |
| addRdnLine( rdnComposite, 0 ); |
| rdnLineList.get( 0 ).rdnTypeCombo.setFocus(); |
| } |
| else |
| { |
| int i = 0; |
| Iterator<Ava> atavIterator = currentRdn.iterator(); |
| while ( atavIterator.hasNext() ) |
| { |
| Ava ava = atavIterator.next(); |
| addRdnLine( rdnComposite, i ); |
| |
| removeRdnLineListeners( i ); |
| |
| rdnLineList.get( i ).rdnTypeCombo.setText( ava.getType() ); |
| rdnLineList.get( i ).rdnValueText.setText( (String)ava.getValue().getNormalized() ); |
| |
| addRdnLineListeners( i ); |
| |
| if ( i == 0 ) |
| { |
| RdnLine rdnLine = rdnLineList.get( i ); |
| |
| if ( rdnLine.rdnTypeCombo != null ) //$NON-NLS-1$ |
| { |
| rdnLine.rdnTypeCombo.setFocus(); |
| } |
| else |
| { |
| rdnLine.rdnValueText.selectAll(); |
| rdnLine.rdnValueText.setFocus(); |
| } |
| } |
| i++; |
| } |
| } |
| } |
| |
| if ( showParent ) |
| { |
| parentEntryWidget.setInput( browserConnection, currentParentDn ); |
| } |
| |
| validate(); |
| } |
| |
| |
| /** |
| * Gets the Rdn. |
| * |
| * @return the Rdn |
| */ |
| public Rdn getRdn() |
| { |
| return rdn; |
| } |
| |
| |
| /** |
| * Gets the parent Dn. |
| * |
| * @return the parent Dn |
| */ |
| public Dn getParentDn() |
| { |
| return parentDn; |
| } |
| |
| |
| /** |
| * Creates the contents. |
| * |
| * @param parent the parent composite |
| * |
| * @return the created composite |
| */ |
| public Composite createContents( Composite parent ) |
| { |
| this.shell = parent.getShell(); |
| |
| Composite composite = BaseWidgetUtils.createColumnContainer( parent, 3, 1 ); |
| |
| // draw parent |
| if ( showParent ) |
| { |
| parentEntryLabel = BaseWidgetUtils.createLabel( composite, |
| Messages.getString( "DnBuilderWidget.Parent" ), 1 ); //$NON-NLS-1$ |
| parentEntryWidget = new EntryWidget(); |
| parentEntryWidget.createWidget( composite ); |
| parentEntryWidget.addWidgetModifyListener( event -> validate() ); |
| |
| BaseWidgetUtils.createSpacer( composite, 3 ); |
| } |
| |
| // draw Rdn group |
| if ( showRDN ) |
| { |
| rdnLabel = BaseWidgetUtils.createLabel( composite, Messages.getString( "DnBuilderWidget.RDN" ), 1 ); //$NON-NLS-1$ |
| rdnComposite = BaseWidgetUtils.createColumnContainer( composite, 5, 2 ); |
| rdnLineList = new ArrayList<>(); |
| BaseWidgetUtils.createSpacer( composite, 3 ); |
| } |
| |
| // draw dn/rdn preview |
| if ( showRDN ) |
| { |
| previewLabel = BaseWidgetUtils.createLabel( composite, showParent ? Messages |
| .getString( "DnBuilderWidget.DNPreview" ) : Messages.getString( "DnBuilderWidget.RDNPreview" ), 1 ); //$NON-NLS-1$ //$NON-NLS-2$ |
| previewText = BaseWidgetUtils.createReadonlyText( composite, "", 2 ); //$NON-NLS-1$ |
| BaseWidgetUtils.createSpacer( composite, 3 ); |
| } |
| |
| return composite; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void modifyText( ModifyEvent e ) |
| { |
| validate(); |
| } |
| |
| |
| /** |
| * Saves the dialog settings. |
| */ |
| public void saveDialogSettings() |
| { |
| if ( parentEntryWidget != null ) |
| { |
| parentEntryWidget.saveDialogSettings(); |
| } |
| } |
| |
| |
| /** |
| * Validates the input elements. |
| */ |
| public void validate() |
| { |
| Exception rdnE = null; |
| |
| if ( showRDN ) |
| { |
| try |
| { |
| // calculate Rdn |
| String[] rdnTypes = new String[rdnLineList.size()]; |
| String[] rdnValues = new String[rdnLineList.size()]; |
| |
| for ( int i = 0; i < rdnLineList.size(); i++ ) |
| { |
| RdnLine rdnLine = rdnLineList.get( i ); |
| rdnTypes[i] = rdnLine.rdnTypeCombo.getText(); |
| rdnValues[i] = rdnLine.rdnValueText.getText(); |
| |
| if ( rdnLineList.size() > 1 ) |
| { |
| rdnLine.rdnDeleteButton.setEnabled( true ); |
| } |
| else |
| { |
| rdnLine.rdnDeleteButton.setEnabled( false ); |
| } |
| } |
| |
| rdn = DnUtils.composeRdn( rdnTypes, rdnValues ); |
| } |
| catch ( Exception e ) |
| { |
| rdnE = e; |
| rdn = null; |
| } |
| } |
| |
| Exception parentE = null; |
| |
| if ( showParent ) |
| { |
| try |
| { |
| // calculate Dn |
| parentDn = parentEntryWidget.getDn(); |
| } |
| catch ( Exception e ) |
| { |
| parentE = e; |
| parentDn = null; |
| } |
| } |
| |
| String s = ""; //$NON-NLS-1$ |
| |
| if ( rdnE != null ) |
| { |
| s += rdnE.getMessage() != null ? rdnE.getMessage() : Messages.getString( "DnBuilderWidget.ErrorInRDN" ); //$NON-NLS-1$ |
| } |
| |
| if ( parentE != null ) |
| { |
| s += ", " + parentE.getMessage() != null ? parentE.getMessage() : Messages.getString( "DnBuilderWidget.ErrorInParentDN" ); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| if ( previewText != null ) |
| { |
| if ( s.length() > 0 ) |
| { |
| previewText.setText( s ); |
| } |
| else |
| { |
| Dn dn; |
| |
| if ( showParent && showRDN ) |
| { |
| try |
| { |
| dn = parentDn.add( rdn ); |
| } |
| catch ( LdapInvalidDnException lide ) |
| { |
| // Do nothing |
| dn = Dn.EMPTY_DN; |
| } |
| } |
| else if ( showParent ) |
| { |
| dn = parentDn; |
| } |
| else if ( showRDN ) |
| { |
| try |
| { |
| dn = new Dn( rdn ); |
| } |
| catch ( LdapInvalidDnException lide ) |
| { |
| // Do nothing |
| dn = Dn.EMPTY_DN; |
| } |
| } |
| else |
| { |
| dn = Dn.EMPTY_DN; |
| } |
| |
| previewText.setText( dn.getName() ); |
| } |
| } |
| |
| notifyListeners(); |
| } |
| |
| |
| /** |
| * Adds an Rdn line at the given index. |
| * |
| * @param rdnComposite the Rdn composite |
| * @param index the index |
| */ |
| private void addRdnLine( Composite rdnComposite, int index ) |
| { |
| RdnLine[] rdnLines = rdnLineList.toArray( new RdnLine[rdnLineList.size()] ); |
| |
| if ( rdnLines.length > 0 ) |
| { |
| for ( int i = 0; i < rdnLines.length; i++ ) |
| { |
| RdnLine oldRdnLine = rdnLines[i]; |
| |
| // remember values |
| String oldName = oldRdnLine.rdnTypeCombo.getText(); |
| String oldValue = oldRdnLine.rdnValueText.getText(); |
| |
| // delete old |
| oldRdnLine.rdnTypeCombo.dispose(); |
| oldRdnLine.rdnEqualsLabel.dispose(); |
| oldRdnLine.rdnValueText.dispose(); |
| oldRdnLine.rdnAddButton.dispose(); |
| oldRdnLine.rdnDeleteButton.dispose(); |
| rdnLineList.remove( oldRdnLine ); |
| |
| // add new |
| RdnLine newRdnLine = createRdnLine( rdnComposite ); |
| rdnLineList.add( newRdnLine ); |
| |
| // restore value |
| newRdnLine.rdnTypeCombo.setText( oldName ); |
| newRdnLine.rdnValueText.setText( oldValue ); |
| |
| // check |
| if ( index == i + 1 ) |
| { |
| RdnLine rdnLine = createRdnLine( rdnComposite ); |
| rdnLineList.add( rdnLine ); |
| } |
| } |
| } |
| else |
| { |
| RdnLine rdnLine = createRdnLine( rdnComposite ); |
| rdnLineList.add( rdnLine ); |
| } |
| |
| shell.layout( true, true ); |
| } |
| |
| |
| /** |
| * Creates and returns an Rdn line. |
| * |
| * @param rdnComposite the Rdn composite |
| * |
| * @return the created Rdn line |
| */ |
| private RdnLine createRdnLine( final Composite rdnComposite ) |
| { |
| final RdnLine rdnLine = new RdnLine(); |
| |
| rdnLine.rdnTypeCombo = new Combo( rdnComposite, SWT.DROP_DOWN | SWT.BORDER ); |
| GridData gd = new GridData(); |
| gd.widthHint = 180; |
| rdnLine.rdnTypeCombo.setLayoutData( gd ); |
| rdnLine.rdnNameCPA = new ExtendedContentAssistCommandAdapter( rdnLine.rdnTypeCombo, new ComboContentAdapter(), |
| new ListContentProposalProvider( attributeNames ), null, null, true ); |
| |
| rdnLine.rdnEqualsLabel = new Label( rdnComposite, SWT.NONE ); |
| rdnLine.rdnEqualsLabel.setText( "=" ); //$NON-NLS-1$ |
| |
| rdnLine.rdnValueText = new Text( rdnComposite, SWT.BORDER ); |
| gd = new GridData( GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL ); |
| rdnLine.rdnValueText.setLayoutData( gd ); |
| |
| rdnLine.rdnAddButton = new Button( rdnComposite, SWT.PUSH ); |
| rdnLine.rdnAddButton.setText( " + " ); //$NON-NLS-1$ |
| |
| rdnLine.rdnDeleteButton = new Button( rdnComposite, SWT.PUSH ); |
| rdnLine.rdnDeleteButton.setText( " \u2212 " ); //$NON-NLS-1$ |
| |
| if ( attributeNames != null ) |
| { |
| rdnLine.rdnTypeCombo.setItems( attributeNames ); |
| } |
| |
| addRdnLineListeners( rdnLine ); |
| |
| return rdnLine; |
| } |
| |
| |
| /** |
| * Delete the Rdn line on the given index. |
| * |
| * @param rdnComposite the Rdn composite |
| * @param index the index |
| */ |
| private void deleteRdnLine( Composite rdnComposite, int index ) |
| { |
| RdnLine rdnLine = rdnLineList.remove( index ); |
| if ( rdnLine != null ) |
| { |
| rdnLine.rdnTypeCombo.dispose(); |
| rdnLine.rdnEqualsLabel.dispose(); |
| rdnLine.rdnValueText.dispose(); |
| rdnLine.rdnAddButton.dispose(); |
| rdnLine.rdnDeleteButton.dispose(); |
| |
| if ( !rdnComposite.isDisposed() ) |
| { |
| shell.layout( true, true ); |
| } |
| } |
| } |
| |
| |
| /** |
| * Adds listeners for the Rdn line at the given index. |
| * |
| * @param index the index |
| */ |
| private void addRdnLineListeners( int index ) |
| { |
| if ( rdnLineList != null ) |
| { |
| addRdnLineListeners( rdnLineList.get( index ) ); |
| } |
| } |
| |
| |
| /** |
| * Adds listeners for the Rdn line. |
| * |
| * @param rdnLine the Rdn line |
| */ |
| private void addRdnLineListeners( RdnLine rdnLine ) |
| { |
| if ( rdnLine != null ) |
| { |
| rdnLine.rdnAddButton.addSelectionListener( rdnAddButtonSelectionListener ); |
| rdnLine.rdnDeleteButton.addSelectionListener( rdnDeleteButtonSelectionListener ); |
| rdnLine.rdnTypeCombo.addModifyListener( this ); |
| rdnLine.rdnValueText.addModifyListener( this ); |
| } |
| } |
| |
| |
| /** |
| * Removes listeners for the Rdn line at the given index. |
| * |
| * @param index the index |
| */ |
| private void removeRdnLineListeners( int index ) |
| { |
| if ( rdnLineList != null ) |
| { |
| removeRdnLineListeners( rdnLineList.get( index ) ); |
| } |
| } |
| |
| |
| /** |
| * Removes listeners for the Rdn line. |
| * |
| * @param rdnLine the Rdn line |
| */ |
| private void removeRdnLineListeners( RdnLine rdnLine ) |
| { |
| if ( rdnLine != null ) |
| { |
| rdnLine.rdnAddButton.removeSelectionListener( rdnAddButtonSelectionListener ); |
| rdnLine.rdnDeleteButton.removeSelectionListener( rdnDeleteButtonSelectionListener ); |
| rdnLine.rdnTypeCombo.removeModifyListener( this ); |
| rdnLine.rdnValueText.removeModifyListener( this ); |
| } |
| } |
| |
| /** |
| * The Class RdnLine is a wrapper for all input elements |
| * of an Rdn line. It contains a combo for the Rdn attribute, |
| * an input field for the Rdn value and + and - buttons |
| * to add and remove other Rdn lines. It looks like this: |
| * <pre> |
| * -------------------------------------------------- |
| * | attribute type v | = | attribute value | + | - | |
| * -------------------------------------------------- |
| * </pre> |
| */ |
| private class RdnLine |
| { |
| |
| /** The rdn name combo. */ |
| private Combo rdnTypeCombo; |
| |
| /** The content proposal adapter */ |
| private ContentProposalAdapter rdnNameCPA; |
| |
| /** The rdn value text. */ |
| private Text rdnValueText; |
| |
| /** The rdn equals label. */ |
| private Label rdnEqualsLabel; |
| |
| /** The rdn add button. */ |
| private Button rdnAddButton; |
| |
| /** The rdn delete button. */ |
| private Button rdnDeleteButton; |
| } |
| |
| |
| /** |
| * Enables or disables this widget. |
| * |
| * @param b true to enable, false to disable |
| */ |
| public void setEnabled( boolean b ) |
| { |
| if ( parentEntryWidget != null ) |
| { |
| parentEntryLabel.setEnabled( b ); |
| parentEntryWidget.setEnabled( b ); |
| } |
| if ( rdnComposite != null && rdnLineList != null ) |
| { |
| rdnLabel.setEnabled( b ); |
| rdnComposite.setEnabled( b ); |
| for ( RdnLine rdnLine : rdnLineList ) |
| { |
| rdnLine.rdnTypeCombo.setEnabled( b ); |
| rdnLine.rdnEqualsLabel.setEnabled( b ); |
| rdnLine.rdnValueText.setEnabled( b ); |
| rdnLine.rdnAddButton.setEnabled( b ); |
| rdnLine.rdnDeleteButton.setEnabled( b && rdnLineList.size() > 1 ); |
| } |
| if ( b ) |
| { |
| rdnLineList.get( 0 ).rdnValueText.setFocus(); |
| } |
| } |
| if ( previewText != null ) |
| { |
| previewLabel.setEnabled( b ); |
| previewText.setEnabled( b ); |
| } |
| } |
| |
| } |