| /* |
| * 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 org.apache.directory.studio.common.ui.widgets.AbstractWidget; |
| import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils; |
| import org.apache.directory.studio.connection.ui.widgets.ExtendedContentAssistCommandAdapter; |
| import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants; |
| import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema; |
| import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils; |
| import org.eclipse.jface.fieldassist.ComboContentAdapter; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ScrolledComposite; |
| 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; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Text; |
| |
| |
| /** |
| * The ModWidget provides input elements to define an LDAP modify |
| * operation. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public class ModWidget extends AbstractWidget |
| { |
| /** The scrolled composite */ |
| private ScrolledComposite scrolledComposite; |
| |
| /** The composite that contains the ModSpecs */ |
| private Composite composite; |
| |
| /** The list of ModSpecs */ |
| private ArrayList<ModSpec> modSpecList = new ArrayList<ModSpec>(); |
| |
| /** The list content proposal provider */ |
| private ListContentProposalProvider listContentProposalProvider; |
| |
| /** The resulting LDIF */ |
| private String ldif; |
| |
| // Listeners |
| private ModifyListener modifyListener = new ModifyListener() |
| { |
| public void modifyText( ModifyEvent e ) |
| { |
| validate( true ); |
| } |
| }; |
| |
| |
| /** |
| * Creates a new instance of ModWidget. |
| * |
| * @param schema the schema with the possible attribute types |
| */ |
| public ModWidget( Schema schema ) |
| { |
| String[] attributeDescriptions = SchemaUtils.getNamesAsArray( schema.getAttributeTypeDescriptions() ); |
| Arrays.sort( attributeDescriptions ); |
| listContentProposalProvider = new ListContentProposalProvider( attributeDescriptions ); |
| } |
| |
| |
| /** |
| * Disposes this widget. |
| */ |
| public void dispose() |
| { |
| } |
| |
| |
| /** |
| * Gets the ldif. |
| * |
| * @return the ldif |
| */ |
| public String getLdif() |
| { |
| return ldif; |
| } |
| |
| |
| /** |
| * Creates the contents. |
| * |
| * @param parent the parent composite |
| * |
| * @return the created composite |
| */ |
| public Composite createContents( Composite parent ) |
| { |
| // Creating the scrolled composite containing all UI |
| scrolledComposite = new ScrolledComposite( parent, SWT.H_SCROLL | SWT.V_SCROLL ); |
| scrolledComposite.setLayout( new GridLayout() ); |
| scrolledComposite.setExpandHorizontal( true ); |
| scrolledComposite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) ); |
| |
| // Creating the composite |
| composite = BaseWidgetUtils.createColumnContainer( scrolledComposite, 3, 1 ); |
| composite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) ); |
| scrolledComposite.setContent( composite ); |
| |
| addInitialModSpec(); |
| |
| validate( false ); |
| |
| return scrolledComposite; |
| } |
| |
| |
| /** |
| * Validates the input elements. |
| */ |
| public void validate( boolean notifyListeners ) |
| { |
| for ( int i = 0; i < modSpecList.size(); i++ ) |
| { |
| ModSpec modSpec = ( ModSpec ) modSpecList.get( i ); |
| if ( modSpecList.size() > 1 ) |
| { |
| modSpec.modDeleteButton.setEnabled( true ); |
| } |
| else |
| { |
| modSpec.modDeleteButton.setEnabled( false ); |
| } |
| for ( int k = 0; k < modSpec.valueLineList.size(); k++ ) |
| { |
| ValueLine valueLine = ( ValueLine ) modSpec.valueLineList.get( k ); |
| if ( modSpec.valueLineList.size() > 1 ) |
| { |
| valueLine.valueDeleteButton.setEnabled( true ); |
| } |
| else |
| { |
| valueLine.valueDeleteButton.setEnabled( false ); |
| } |
| } |
| } |
| |
| if ( notifyListeners ) |
| { |
| notifyListeners(); |
| } |
| } |
| |
| |
| /** |
| * Adds an initial modification spec. |
| * |
| */ |
| private void addInitialModSpec() |
| { |
| addModSpec( 0 ); |
| } |
| |
| |
| /** |
| * Adds a modification spec at the given index. |
| * |
| * @param index the index |
| */ |
| private void addModSpec( int index ) |
| { |
| // Getting the array of modification specs |
| ModSpec[] modSpecs = ( ModSpec[] ) modSpecList.toArray( new ModSpec[modSpecList.size()] ); |
| |
| // Adding a new modification spec |
| ModSpec newModSpec = createModSpec( true ); |
| modSpecList.add( newModSpec ); |
| |
| if ( modSpecs.length > 0 ) |
| { |
| for ( int i = index; i < modSpecs.length; i++ ) |
| { |
| ModSpec modSpec = modSpecs[i]; |
| |
| // That's a trick to relocate the modification spec |
| // beneath the newly created one |
| modSpec.modGroup.setParent( scrolledComposite ); |
| modSpec.modAddButton.setParent( scrolledComposite ); |
| modSpec.modDeleteButton.setParent( scrolledComposite ); |
| modSpec.modGroup.setParent( composite ); |
| modSpec.modAddButton.setParent( composite ); |
| modSpec.modDeleteButton.setParent( composite ); |
| |
| // Same trick to update the id in the list |
| modSpecList.remove( modSpec ); |
| modSpecList.add( modSpec ); |
| } |
| } |
| |
| composite.setSize( composite.computeSize( SWT.DEFAULT, SWT.DEFAULT ) ); |
| } |
| |
| |
| /** |
| * Creates and returns a modification spec. |
| * |
| * @param addFirstValueLine if a first value line should added |
| * @return the created modification spec |
| */ |
| private ModSpec createModSpec( boolean addFirstValueLine ) |
| { |
| ModSpec modSpec = new ModSpec(); |
| |
| modSpec.modGroup = BaseWidgetUtils.createGroup( composite, "", 1 ); //$NON-NLS-1$ |
| modSpec.modGroup.setLayoutData( new GridData( SWT.FILL, SWT.NONE, true, false ) ); |
| Composite modSpecComposite = BaseWidgetUtils.createColumnContainer( modSpec.modGroup, 2, 1 ); |
| modSpec.modType = BaseWidgetUtils.createReadonlyCombo( modSpecComposite, new String[] |
| { "add", "replace", "delete" }, 0, 1 ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| modSpec.modType.setLayoutData( new GridData() ); |
| modSpec.modType.addModifyListener( modifyListener ); |
| |
| // attribute combo with field decoration and content proposal |
| modSpec.modAttributeCombo = BaseWidgetUtils.createCombo( modSpecComposite, new String[0], -1, 1 ); |
| new ExtendedContentAssistCommandAdapter( modSpec.modAttributeCombo, new ComboContentAdapter(), |
| listContentProposalProvider, null, null, true ); |
| modSpec.modAttributeCombo.addModifyListener( modifyListener ); |
| |
| // add button with listener |
| modSpec.modAddButton = new Button( composite, SWT.PUSH ); |
| modSpec.modAddButton.setText( " + " ); //$NON-NLS-1$ |
| modSpec.modAddButton.addSelectionListener( new SelectionAdapter() |
| { |
| public void widgetSelected( SelectionEvent e ) |
| { |
| int index = modSpecList.size(); |
| for ( int i = 0; i < modSpecList.size(); i++ ) |
| { |
| ModSpec modSpec = modSpecList.get( i ); |
| if ( modSpec.modAddButton == e.widget ) |
| { |
| index = i + 1; |
| } |
| } |
| |
| addModSpec( index ); |
| |
| validate( true ); |
| } |
| } ); |
| |
| // delete button with listener |
| modSpec.modDeleteButton = new Button( composite, SWT.PUSH ); |
| modSpec.modDeleteButton.setText( " \u2212 " ); //$NON-NLS-1$ |
| modSpec.modDeleteButton.addSelectionListener( new SelectionAdapter() |
| { |
| public void widgetSelected( SelectionEvent e ) |
| { |
| int index = 0; |
| for ( int i = 0; i < modSpecList.size(); i++ ) |
| { |
| ModSpec modSpec = modSpecList.get( i ); |
| if ( modSpec.modDeleteButton == e.widget ) |
| { |
| index = i; |
| } |
| } |
| |
| deleteModSpec( index ); |
| |
| validate( true ); |
| } |
| } ); |
| |
| if ( addFirstValueLine ) |
| { |
| addValueLine( modSpec, 0, false ); |
| } |
| |
| return modSpec; |
| } |
| |
| |
| /** |
| * Delets a modification spec. |
| * |
| * @param index the index |
| */ |
| private void deleteModSpec( int index ) |
| { |
| ModSpec modSpec = modSpecList.remove( index ); |
| if ( modSpec != null ) |
| { |
| modSpec.modGroup.dispose(); |
| modSpec.modAddButton.dispose(); |
| modSpec.modDeleteButton.dispose(); |
| |
| composite.setSize( composite.computeSize( SWT.DEFAULT, SWT.DEFAULT ) ); |
| } |
| } |
| |
| |
| /** |
| * Adds a value line to the given modification spec. |
| * |
| * @param modSpec the modification spec |
| * @param index the index |
| * @param boolean the flag to update the size |
| */ |
| private void addValueLine( ModSpec modSpec, int index, boolean updateSize ) |
| { |
| ValueLine[] valueLines = modSpec.valueLineList.toArray( new ValueLine[modSpec.valueLineList.size()] ); |
| |
| ValueLine newValueLine = createValueLine( modSpec ); |
| modSpec.valueLineList.add( newValueLine ); |
| |
| if ( valueLines.length > 0 ) |
| { |
| for ( int i = index; i < valueLines.length; i++ ) |
| { |
| ValueLine valueLine = valueLines[i]; |
| |
| // That's a trick to relocate the value line |
| // beneath the newly created one |
| Composite parentComposite = valueLine.valueComposite.getParent(); |
| valueLine.valueComposite.setParent( scrolledComposite ); |
| valueLine.valueComposite.setParent( parentComposite ); |
| |
| // Same trick to update the id in the list |
| modSpec.valueLineList.remove( valueLine ); |
| modSpec.valueLineList.add( valueLine ); |
| } |
| } |
| |
| if ( updateSize ) |
| { |
| composite.setSize( composite.computeSize( SWT.DEFAULT, SWT.DEFAULT ) ); |
| } |
| } |
| |
| |
| /** |
| * Creates the value line. |
| * |
| * @param modSpec the modification spec |
| * |
| * @return the value line |
| */ |
| private ValueLine createValueLine( final ModSpec modSpec ) |
| { |
| final ValueLine valueLine = new ValueLine(); |
| |
| // text field |
| valueLine.valueComposite = BaseWidgetUtils.createColumnContainer( modSpec.modGroup, 3, 1 ); |
| valueLine.valueText = BaseWidgetUtils.createText( valueLine.valueComposite, "", 1 ); //$NON-NLS-1$ |
| valueLine.valueText.addModifyListener( modifyListener ); |
| |
| // add button with listener |
| valueLine.valueAddButton = new Button( valueLine.valueComposite, SWT.PUSH ); |
| valueLine.valueAddButton.setText( " + " ); //$NON-NLS-1$ |
| valueLine.valueAddButton.addSelectionListener( new SelectionAdapter() |
| { |
| public void widgetSelected( SelectionEvent e ) |
| { |
| int index = modSpec.valueLineList.size(); |
| for ( int i = 0; i < modSpec.valueLineList.size(); i++ ) |
| { |
| ValueLine valueLine = modSpec.valueLineList.get( i ); |
| if ( valueLine.valueAddButton == e.widget ) |
| { |
| index = i + 1; |
| } |
| } |
| |
| addValueLine( modSpec, index, true ); |
| |
| validate( true ); |
| } |
| } ); |
| |
| // delete button with listener |
| valueLine.valueDeleteButton = new Button( valueLine.valueComposite, SWT.PUSH ); |
| valueLine.valueDeleteButton.setText( " \u2212 " ); //$NON-NLS-1$ |
| valueLine.valueDeleteButton.addSelectionListener( new SelectionAdapter() |
| { |
| public void widgetSelected( SelectionEvent e ) |
| { |
| int index = 0; |
| for ( int i = 0; i < modSpec.valueLineList.size(); i++ ) |
| { |
| ValueLine valueLine = modSpec.valueLineList.get( i ); |
| if ( valueLine.valueDeleteButton == e.widget ) |
| { |
| index = i; |
| } |
| } |
| |
| deleteValueLine( modSpec, index ); |
| |
| validate( true ); |
| } |
| } ); |
| |
| return valueLine; |
| } |
| |
| |
| /** |
| * Delete value line. |
| * |
| * @param modSpec the mod spec |
| * @param index the index |
| */ |
| private void deleteValueLine( ModSpec modSpec, int index ) |
| { |
| ValueLine valueLine = ( ValueLine ) modSpec.valueLineList.remove( index ); |
| if ( valueLine != null ) |
| { |
| valueLine.valueComposite.dispose(); |
| |
| composite.setSize( composite.computeSize( SWT.DEFAULT, SWT.DEFAULT ) ); |
| } |
| } |
| |
| |
| /** |
| * Gets the LDIF fragment. |
| * |
| * @return the LDIF fragment |
| */ |
| public String getLdifFragment() |
| { |
| StringBuffer sb = new StringBuffer(); |
| sb.append( "changetype: modify" ).append( BrowserCoreConstants.LINE_SEPARATOR ); //$NON-NLS-1$ |
| |
| ModSpec[] modSpecs = ( ModSpec[] ) modSpecList.toArray( new ModSpec[modSpecList.size()] ); |
| |
| if ( modSpecs.length > 0 ) |
| { |
| for ( int i = 0; i < modSpecs.length; i++ ) |
| { |
| ModSpec modSpec = modSpecs[i]; |
| |
| // get values |
| String type = modSpec.modType.getText(); |
| String attribute = modSpec.modAttributeCombo.getText(); |
| String[] values = new String[modSpec.valueLineList.size()]; |
| for ( int k = 0; k < values.length; k++ ) |
| { |
| values[k] = ( ( ValueLine ) modSpec.valueLineList.get( k ) ).valueText.getText(); |
| } |
| |
| // build ldif |
| sb.append( type ).append( ": " ).append( attribute ).append( BrowserCoreConstants.LINE_SEPARATOR ); //$NON-NLS-1$ |
| for ( int k = 0; k < values.length; k++ ) |
| { |
| if ( values[k].length() > 0 ) |
| { |
| sb.append( attribute ).append( ": " ).append( values[k] ).append( //$NON-NLS-1$ |
| BrowserCoreConstants.LINE_SEPARATOR ); |
| } |
| } |
| sb.append( "-" ).append( BrowserCoreConstants.LINE_SEPARATOR ); //$NON-NLS-1$ |
| // sb.append(BrowserCoreConstants.NEWLINE); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * The Class ModSpec is a wrapper for all input elements |
| * of an modification. It contains a combo for the modify |
| * operation, a combo for the attribute to modify, |
| * value lines and + and - buttons to add and remove |
| * other modifications. It looks like this: |
| * <pre> |
| * ---------------------------------- |
| * | operation v | attribute type v |-------- |
| * ------------------------ --------| + | - | |
| * | value | + | - |-------- |
| * ---------------------------------- |
| * </pre> |
| */ |
| private class ModSpec |
| { |
| /** The mod group. */ |
| private Group modGroup; |
| |
| /** The mod type. */ |
| private Combo modType; |
| |
| /** The modification attribute. */ |
| private Combo modAttributeCombo; |
| |
| /** The mod add button. */ |
| private Button modAddButton; |
| |
| /** The mod delete button. */ |
| private Button modDeleteButton; |
| |
| /** The value line list. */ |
| private ArrayList<ValueLine> valueLineList = new ArrayList<ValueLine>();; |
| } |
| |
| /** |
| * The Class ValueLine is a wrapper for all input elements |
| * of an value line. It contains an input field for the value |
| * and + and - buttons to add and remove other value lines. |
| * It looks like this: |
| * <pre> |
| * ------------------------------------- |
| * | value | + | - | |
| * ------------------------------------- |
| * </pre> |
| */ |
| private class ValueLine |
| { |
| /** The value composite. */ |
| private Composite valueComposite; |
| |
| /** The value text. */ |
| private Text valueText; |
| |
| /** The value add button. */ |
| private Button valueAddButton; |
| |
| /** The value delete button. */ |
| private Button valueDeleteButton; |
| } |
| } |