Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 89950 invoked from network); 5 Nov 2007 14:29:02 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 5 Nov 2007 14:29:02 -0000 Received: (qmail 34762 invoked by uid 500); 5 Nov 2007 14:28:50 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 34696 invoked by uid 500); 5 Nov 2007 14:28:50 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 34537 invoked by uid 99); 5 Nov 2007 14:28:49 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 Nov 2007 06:28:49 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 Nov 2007 14:29:20 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 6B05C1A9846; Mon, 5 Nov 2007 06:28:29 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r592011 [4/6] - in /directory/sandbox/felixk/studio-aciitemeditor: ./ META-INF/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/studio/ src/ma... Date: Mon, 05 Nov 2007 14:28:02 -0000 To: commits@directory.apache.org From: felixk@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20071105142829.6B05C1A9846@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeSpecificationDialog.java URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeSpecificationDialog.java?rev=592011&view=auto ============================================================================== --- directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeSpecificationDialog.java (added) +++ directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeSpecificationDialog.java Mon Nov 5 06:27:47 2007 @@ -0,0 +1,726 @@ +/* + * 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.aciitemeditor.valueeditors; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.directory.shared.ldap.name.LdapDN; +import org.apache.directory.shared.ldap.subtree.BaseSubtreeSpecification; +import org.apache.directory.shared.ldap.subtree.SubtreeSpecification; +import org.apache.directory.shared.ldap.subtree.SubtreeSpecificationParser; +import org.apache.directory.studio.aciitemeditor.Activator; +import org.apache.directory.studio.ldapbrowser.common.dialogs.TextDialog; +import org.apache.directory.studio.ldapbrowser.common.widgets.BaseWidgetUtils; +import org.apache.directory.studio.ldapbrowser.common.widgets.WidgetModifyEvent; +import org.apache.directory.studio.ldapbrowser.common.widgets.WidgetModifyListener; +import org.apache.directory.studio.ldapbrowser.common.widgets.search.EntryWidget; +import org.apache.directory.studio.ldapbrowser.common.widgets.search.FilterWidget; +import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection; +import org.apache.directory.studio.ldapbrowser.core.utils.DnUtils; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +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.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Spinner; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.Text; + +/** + * This class provides a dialog to enter the Subtree Specification value. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +class SubtreeSpecificationDialog extends Dialog +{ + + /** The parser. */ + private final SubtreeSpecificationParser parser = new SubtreeSpecificationParser( null ); + + /** The connection */ + private IBrowserConnection connection; + + /** The subentry's DN */ + private LdapDN subentryDN; + + /** Flag indicating if the refinement or filter widget should be visible */ + private boolean refinementOrFilterVisible; + + /** The initial SubtreeSpecification */ + private SubtreeSpecification subtreeSpecification; + + /** The Exclusions List */ + private List exclusions; + + /** The returned SubtreeSpecification */ + private String returnValue; + + // UI Fields + private EntryWidget entryWidget; + private Spinner minimumSpinner; + private Spinner maximumSpinner; + private TableViewer exclusionsTableViewer; + private Button exclusionsTableAddButton; + private Button exclusionsTableEditButton; + private Button exclusionsTableDeleteButton; + private Button refinementButton; + private Text refinementText; + private Button filterButton; + private FilterWidget filterWidget; + + + /** + * Creates a new instance of SubtreeSpecificationDialog. + * + * @param shell + * the shell to use + * @param connection + * the connection to use + * @param subentryDN + * the subentry's DN + * @param initialSubtreeSpecification + * the initial SubtreeSpecification + * @param refinementOrFilterVisible + * true if the refinement of filter widget should be visible + */ + SubtreeSpecificationDialog( Shell shell, IBrowserConnection connection, LdapDN subentryDN, + String initialSubtreeSpecification, boolean refinementOrFilterVisible ) + { + super( shell ); + this.connection = connection; + this.subentryDN = subentryDN; + this.refinementOrFilterVisible = refinementOrFilterVisible; + + // parse + try + { + subtreeSpecification = parser.parse( initialSubtreeSpecification ); + if ( subtreeSpecification == null ) + { + subtreeSpecification = new BaseSubtreeSpecification(); + } + } + catch ( ParseException pe ) + { + // TODO + pe.printStackTrace(); + subtreeSpecification = new BaseSubtreeSpecification(); + } + + exclusions = new ArrayList(); + Set chopBeforeExclusions = subtreeSpecification.getChopBeforeExclusions(); + for ( Object chopBeforeExclusion : chopBeforeExclusions ) + { + LdapDN dn = ( LdapDN ) chopBeforeExclusion; + exclusions.add( "chopBefore: \"" + dn.toNormName() + "\"" ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + Set chopAfterExclusions = subtreeSpecification.getChopAfterExclusions(); + for ( Object chopAfterExclusion : chopAfterExclusions ) + { + LdapDN dn = ( LdapDN ) chopAfterExclusion; + exclusions.add( "chopAfter: \"" + dn.toNormName() + "\"" ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + returnValue = null; + } + + + /** (non-Javadoc) + * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) + */ + protected void configureShell( Shell newShell ) + { + super.configureShell( newShell ); + newShell.setText( Messages.getString( "SubtreeValueEditor.title" ) ); //$NON-NLS-1$ + newShell.setImage( Activator.getDefault().getImage( Messages.getString( "SubtreeValueEditor.icon" ) ) ); //$NON-NLS-1$ + } + + + /** (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#okPressed() + */ + protected void okPressed() + { + // set return value + //returnValue = buildSubreeSpecification(); + StringBuffer sb = new StringBuffer(); + subtreeSpecification.printToBuffer( sb ); + returnValue = sb.toString(); + + // save filter and dn history + if ( refinementOrFilterVisible ) + { + filterWidget.saveDialogSettings(); + } + entryWidget.saveDialogSettings(); + + super.okPressed(); + } + + + /** (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea( Composite parent ) + { + Composite outer = ( Composite ) super.createDialogArea( parent ); + GridData gd = new GridData( GridData.FILL_BOTH ); + gd.widthHint = convertHorizontalDLUsToPixels( IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH ); + outer.setLayoutData( gd ); + + Composite composite = BaseWidgetUtils.createColumnContainer( outer, 3, 1 ); + + BaseWidgetUtils.createLabel( composite, Messages.getString( "SubtreeValueEditor.label.base" ), 1 ); //$NON-NLS-1$ + + LdapDN base = subtreeSpecification.getBase(); + LdapDN suffix = subentryDN != null ? DnUtils.getParent( subentryDN ) : null; + entryWidget = new EntryWidget( connection, base, suffix ); + entryWidget.createWidget( composite ); + entryWidget.addWidgetModifyListener( new WidgetModifyListener() + { + public void widgetModified( WidgetModifyEvent event ) + { + validate(); + } + } ); + + GridData spinnersGridData = new GridData(); + spinnersGridData.grabExcessHorizontalSpace = true; + spinnersGridData.verticalAlignment = GridData.CENTER; + spinnersGridData.horizontalSpan = 2; + spinnersGridData.horizontalAlignment = GridData.BEGINNING; + spinnersGridData.widthHint = 3 * 12; + + BaseWidgetUtils.createLabel( composite, Messages.getString( "SubtreeValueEditor.label.minimum" ), 1 ); //$NON-NLS-1$ + minimumSpinner = new Spinner( composite, SWT.BORDER ); + minimumSpinner.setMinimum( 0 ); + minimumSpinner.setMaximum( Integer.MAX_VALUE ); + minimumSpinner.setDigits( 0 ); + minimumSpinner.setIncrement( 1 ); + minimumSpinner.setPageIncrement( 100 ); + minimumSpinner.setSelection( subtreeSpecification.getMinBaseDistance() ); + minimumSpinner.setLayoutData( spinnersGridData ); + minimumSpinner.addModifyListener( new ModifyListener() + { + public void modifyText( ModifyEvent event ) + { + validate(); + } + } ); + + BaseWidgetUtils.createLabel( composite, Messages.getString( "SubtreeValueEditor.label.maximum" ), 1 ); //$NON-NLS-1$ + maximumSpinner = new Spinner( composite, SWT.BORDER ); + maximumSpinner.setMinimum( 0 ); + maximumSpinner.setMaximum( Integer.MAX_VALUE ); + maximumSpinner.setDigits( 0 ); + maximumSpinner.setIncrement( 1 ); + maximumSpinner.setPageIncrement( 100 ); + maximumSpinner.setSelection( subtreeSpecification.getMaxBaseDistance() ); + maximumSpinner.setLayoutData( spinnersGridData ); + maximumSpinner.addModifyListener( new ModifyListener() + { + public void modifyText( ModifyEvent event ) + { + validate(); + } + } ); + + createExclusionsTable( composite ); + + if ( refinementOrFilterVisible ) + { + BaseWidgetUtils.createSpacer( composite, 3 ); + createRefinementOrFilterWidgets( composite ); + } + + applyDialogFont( outer ); + + initFromInput(); + + validate(); + + return outer; + } + + + /** + * Initializes the Value Editor from the input. + */ + private void initFromInput() + { + + } + + + /** + * Creates the Exclusions Table. + * + * @param composite + * the composite + */ + private void createExclusionsTable( Composite composite ) + { + GridData tableGridData = new GridData(); + tableGridData.grabExcessHorizontalSpace = true; + tableGridData.verticalAlignment = GridData.FILL; + tableGridData.horizontalAlignment = GridData.FILL; + tableGridData.heightHint = 100; + + BaseWidgetUtils.createLabel( composite, Messages.getString( "SubtreeValueEditor.label.exclusions" ), 1 ); //$NON-NLS-1$ + Table exclusionsTable = new Table( composite, SWT.BORDER ); + exclusionsTable.setHeaderVisible( false ); + exclusionsTable.setLayoutData( tableGridData ); + exclusionsTable.setLinesVisible( false ); + exclusionsTableViewer = new TableViewer( exclusionsTable ); + exclusionsTableViewer.setContentProvider( new ArrayContentProvider() ); + exclusionsTableViewer.setLabelProvider( new LabelProvider() ); + exclusionsTableViewer.setInput( exclusions ); + exclusionsTableViewer.addSelectionChangedListener( new ISelectionChangedListener() + { + public void selectionChanged( SelectionChangedEvent event ) + { + valueSelectedExclusionsTable(); + } + } ); + exclusionsTableViewer.addDoubleClickListener( new IDoubleClickListener() + { + public void doubleClick( DoubleClickEvent event ) + { + editValueExclusionsTable(); + } + } ); + + GridLayout gridLayout = new GridLayout(); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.CENTER; + gridData.grabExcessHorizontalSpace = false; + gridData.grabExcessVerticalSpace = false; + gridData.verticalAlignment = GridData.FILL; + + Composite buttonComposite = new Composite( composite, SWT.NONE ); + buttonComposite.setLayoutData( gridData ); + buttonComposite.setLayout( gridLayout ); + + GridData buttonGridData = new GridData(); + buttonGridData.horizontalAlignment = GridData.FILL; + buttonGridData.grabExcessHorizontalSpace = false; + buttonGridData.verticalAlignment = GridData.BEGINNING; + buttonGridData.widthHint = Activator.getButtonWidth( buttonComposite ); + + exclusionsTableAddButton = new Button( buttonComposite, SWT.PUSH ); + exclusionsTableAddButton.setText( Messages.getString( "SubtreeValueEditor.button.add" ) ); //$NON-NLS-1$ + exclusionsTableAddButton.setLayoutData( buttonGridData ); + exclusionsTableAddButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + addValueExclusionsTable(); + } + } ); + + exclusionsTableEditButton = new Button( buttonComposite, SWT.PUSH ); + exclusionsTableEditButton.setText( Messages.getString( "SubtreeValueEditor.button.edit" ) ); //$NON-NLS-1$ + exclusionsTableEditButton.setLayoutData( buttonGridData ); + exclusionsTableEditButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + editValueExclusionsTable(); + } + } ); + exclusionsTableEditButton.setEnabled( false ); + + exclusionsTableDeleteButton = new Button( buttonComposite, SWT.PUSH ); + exclusionsTableDeleteButton.setText( Messages.getString( "SubtreeValueEditor.button.delete" ) ); //$NON-NLS-1$ + exclusionsTableDeleteButton.setLayoutData( buttonGridData ); + exclusionsTableDeleteButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + deleteValueExclusionsTable(); + } + } ); + exclusionsTableDeleteButton.setEnabled( false ); + } + + + /** + * Creates the refinement or filter widgets + * + * @param composite + * the composite + */ + private void createRefinementOrFilterWidgets( Composite parent ) + { + // Messages.getString( "SubtreeValueEditor.label.exclusions" ) + BaseWidgetUtils.createLabel( parent, Messages + .getString( "SubtreeValueEditor.SubtreeValueEditor.label.refinementOrFilter" ), 1 ); //$NON-NLS-1$ + + Composite composite = BaseWidgetUtils.createColumnContainer( parent, 2, 2 ); + + // refinement redio button + refinementButton = BaseWidgetUtils.createRadiobutton( composite, Messages + .getString( "SubtreeValueEditor.SubtreeValueEditor.label.refinement" ), 2 ); //$NON-NLS-1$ + + // refinement text + refinementText = new Text( composite, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL ); + GridData gd = new GridData( GridData.FILL_BOTH ); + gd.horizontalSpan = 2; + gd.widthHint = convertHorizontalDLUsToPixels( IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH ); + gd.heightHint = convertHorizontalDLUsToPixels( IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH / 6 ); + refinementText.setLayoutData( gd ); + try + { + StringBuffer refinementBuffer = new StringBuffer(); + if ( subtreeSpecification.getRefinement() != null ) + { + subtreeSpecification.getRefinement().printRefinementToBuffer( refinementBuffer ); + } + refinementText.setText( refinementBuffer.toString().trim() ); + refinementText.setEnabled( true ); + refinementButton.setSelection( true ); + } + catch ( UnsupportedOperationException e ) + { + // thrown if the ExprNode doesn't represent a valid refinement + refinementText.setText( "" ); //$NON-NLS-1$ + refinementText.setEnabled( false ); + refinementButton.setSelection( false ); + } + + // filter radio button + filterButton = BaseWidgetUtils.createRadiobutton( composite, Messages + .getString( "SubtreeValueEditor.SubtreeValueEditor.label.filter" ), 2 ); //$NON-NLS-1$ + + // filter widget + StringBuffer filterBuffer = new StringBuffer(); + if ( subtreeSpecification.getRefinement() != null ) + { + subtreeSpecification.getRefinement().printToBuffer( filterBuffer ); + } + filterWidget = new FilterWidget( connection, filterBuffer.toString().trim() ); + filterWidget.createWidget( composite ); + filterButton.setSelection( !refinementButton.getSelection() ); + filterWidget.setEnabled( !refinementButton.getSelection() ); + + // add listeners + refinementButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent arg0 ) + { + refinementText.setEnabled( true ); + //filterButton.setSelection( false ); + filterWidget.setEnabled( false ); + validate(); + } + } ); + refinementText.addModifyListener( new ModifyListener() + { + public void modifyText( ModifyEvent event ) + { + validate(); + } + } ); + filterButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent arg0 ) + { + //refinementButton.setSelection( false ); + refinementText.setEnabled( false ); + filterWidget.setEnabled( true ); + validate(); + } + } ); + filterWidget.addWidgetModifyListener( new WidgetModifyListener() + { + public void widgetModified( WidgetModifyEvent event ) + { + validate(); + } + } ); + } + + + /** + * Validates if the composed subtree specification is valid. + */ + private void validate() + { + boolean valid = true; + + LdapDN base = entryWidget.getDn(); + valid &= base != null; + + String ss = buildSubreeSpecification(); + + try + { + subtreeSpecification = parser.parse( ss ); + valid &= true; + } + catch ( ParseException pe ) + { + subtreeSpecification = null; + valid &= false; + } + + if ( refinementOrFilterVisible && filterButton.getSelection() ) + { + valid &= filterWidget.getFilter() != null; + } + + if ( getButton( IDialogConstants.OK_ID ) != null ) + { + getButton( IDialogConstants.OK_ID ).setEnabled( valid ); + } + + //System.out.println("1:" + ss); + //StringBuffer sb = new StringBuffer(); + //subtreeSpecification.printToBuffer( sb ); + //System.out.println("2:" + sb.toString()); + } + + + private String buildSubreeSpecification() + { + // build subtree specification tree + StringBuffer sb = new StringBuffer(); + sb.append( "{" ); //$NON-NLS-1$ + + // Adding base + LdapDN base = entryWidget.getDn(); + if ( base != null && !SubtreeValueEditor.EMPTY.equals( base.toString() ) ) + { + sb.append( " base \"" + base.toString() + "\"," ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Adding Minimum + int minimum = minimumSpinner.getSelection(); + if ( minimum != 0 ) + { + sb.append( " minimum " + minimum + "," ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Adding Maximum + int maximum = maximumSpinner.getSelection(); + if ( maximum != 0 ) + { + sb.append( " maximum " + maximum + "," ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Adding Exclusions + if ( !exclusions.isEmpty() ) + { + sb.append( " specificExclusions {" ); //$NON-NLS-1$ + + for ( Iterator it = exclusions.iterator(); it.hasNext(); ) + { + sb.append( " " + it.next() ); //$NON-NLS-1$ + + if ( it.hasNext() ) + { + sb.append( "," ); //$NON-NLS-1$ + } + } + + sb.append( " }," ); //$NON-NLS-1$ + } + + // Add Refinement or Filter + String refinementOrFilter = ""; //$NON-NLS-1$ + if ( refinementOrFilterVisible ) + { + if ( refinementButton.getSelection() ) + { + refinementOrFilter = refinementText.getText(); + } + else + { + refinementOrFilter = filterWidget.getFilter(); + } + } + else + { + refinementOrFilter = ""; //$NON-NLS-1$ + } + if ( refinementOrFilter != null && !SubtreeValueEditor.EMPTY.equals( refinementOrFilter ) ) + { + sb.append( " specificationFilter " + refinementOrFilter + "," ); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Removing the last ',' + if ( sb.charAt( sb.length() - 1 ) == ',' ) + { + sb.deleteCharAt( sb.length() - 1 ); + } + + sb.append( " }" ); //$NON-NLS-1$ + + return sb.toString(); + } + + + /** + * Called when value is selected in Exclusions table viewer. + * Updates the enabled/disabled state of the buttons. + */ + private void valueSelectedExclusionsTable() + { + String value = getSelectedValueExclusionsTable(); + + if ( value == null ) + { + exclusionsTableEditButton.setEnabled( false ); + exclusionsTableDeleteButton.setEnabled( false ); + } + else + { + exclusionsTableEditButton.setEnabled( true ); + exclusionsTableDeleteButton.setEnabled( true ); + } + } + + + /** + * Retuns the current selection in the Exclusions table viewer. + * + * @return + * the value that is selected in the Exclusions table viewer, or null. + */ + private String getSelectedValueExclusionsTable() + { + String value = null; + + IStructuredSelection selection = ( IStructuredSelection ) exclusionsTableViewer.getSelection(); + if ( !selection.isEmpty() ) + { + Object element = selection.getFirstElement(); + if ( element instanceof String ) + { + value = ( String ) element; + } + } + + return value; + } + + + /** + * Opens the editor and adds the new Exclusion value to the list. + */ + private void addValueExclusionsTable() + { + LdapDN chopBase = subtreeSpecification.getBase(); + if ( subentryDN != null && DnUtils.getParent( subentryDN ) != null ) + { + LdapDN suffix = subentryDN != null ? DnUtils.getParent( subentryDN ) : null; + chopBase = DnUtils.composeDn( chopBase, suffix ); + } + + ExclusionDialog dialog = new ExclusionDialog( getShell(), connection, chopBase, "" ); //$NON-NLS-1$ + if ( dialog.open() == TextDialog.OK && !SubtreeValueEditor.EMPTY.equals( dialog.getType() ) && !SubtreeValueEditor.EMPTY.equals( dialog.getDN() ) ) + { + String newValue = dialog.getType() + ": \"" + dialog.getDN() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ + exclusions.add( newValue ); + exclusionsTableViewer.refresh(); + validate(); + } + } + + + /** + * Opens the editor with the currently selected Exclusion + * value and puts the modified value into the list. + */ + private void editValueExclusionsTable() + { + String oldValue = getSelectedValueExclusionsTable(); + if ( oldValue != null ) + { + LdapDN chopBase = subtreeSpecification.getBase(); + if ( subentryDN != null && DnUtils.getParent( subentryDN ) != null ) + { + LdapDN suffix = subentryDN != null ? DnUtils.getParent( subentryDN ) : null; + chopBase = DnUtils.composeDn( chopBase, suffix ); + } + + ExclusionDialog dialog = new ExclusionDialog( getShell(), connection, chopBase, oldValue ); + if ( dialog.open() == TextDialog.OK && !SubtreeValueEditor.EMPTY.equals( dialog.getType() ) + && !SubtreeValueEditor.EMPTY.equals( dialog.getDN() ) ) + { + String newValue = dialog.getType() + ": \"" + dialog.getDN() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ + exclusions.remove( oldValue ); + exclusions.add( newValue ); + exclusionsTableViewer.refresh(); + validate(); + } + } + } + + + /** + * Deletes the currently selected Exclusion value from list. + */ + private void deleteValueExclusionsTable() + { + String value = getSelectedValueExclusionsTable(); + if ( value != null ) + { + exclusions.remove( value ); + exclusionsTableViewer.refresh(); + validate(); + } + } + + + /** + * Gets the subtree specification value or null if canceled. + * + * @return the subtree specification value or null if canceled + */ + public String getSubtreeSpecificationValue() + { + return returnValue; + } +} \ No newline at end of file Propchange: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeSpecificationDialog.java ------------------------------------------------------------------------------ svn:eol-style = native Added: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeValueEditor.java URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeValueEditor.java?rev=592011&view=auto ============================================================================== --- directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeValueEditor.java (added) +++ directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeValueEditor.java Mon Nov 5 06:27:47 2007 @@ -0,0 +1,151 @@ +/* + * 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.aciitemeditor.valueeditors; + + + +import org.apache.directory.shared.ldap.name.LdapDN; +import org.apache.directory.studio.ldapbrowser.common.dialogs.TextDialog; +import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection; +import org.apache.directory.studio.ldapbrowser.core.model.IValue; +import org.apache.directory.studio.valueeditors.AbstractDialogStringValueEditor; +import org.apache.directory.studio.valueeditors.ValueEditorManager; +import org.eclipse.swt.widgets.Shell; + + +/** + * ACI item editor specific value editor to edit the SubtreeSpecification. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class SubtreeValueEditor extends AbstractDialogStringValueEditor +{ + static final String EMPTY = ""; //$NON-NLS-1$ + + private boolean refinementOrFilterVisible; + + + /** + * Default constructor, used by the {@link ValueEditorManager}. + */ + public SubtreeValueEditor() + { + this.refinementOrFilterVisible = true; + } + + + /** + * Default constructor, used by the {@link ValueEditorManager}. + * + * @param refinementOrFilterVisible true if the refinement or filter widget should be visible + */ + public SubtreeValueEditor( boolean refinementOrFilterVisible ) + { + this.refinementOrFilterVisible = refinementOrFilterVisible; + } + + + /** + * @see org.apache.directory.studio.valueeditors.AbstractDialogValueEditor#openDialog(org.eclipse.swt.widgets.Shell) + */ + protected boolean openDialog( Shell shell ) + { + Object value = getValue(); + if ( value != null && value instanceof SubtreeSpecificationValueWrapper ) + { + SubtreeSpecificationValueWrapper wrapper = ( SubtreeSpecificationValueWrapper ) value; + + SubtreeSpecificationDialog dialog = new SubtreeSpecificationDialog( shell, wrapper.connection, + wrapper.subentryDN, wrapper.subtreeSpecification, refinementOrFilterVisible ); + if ( dialog.open() == TextDialog.OK && dialog.getSubtreeSpecificationValue() != null ) + { + setValue( dialog.getSubtreeSpecificationValue() ); + return true; + } + } + return false; + } + + + /** + * @see org.apache.directory.studio.valueeditors.AbstractDialogStringValueEditor#getRawValue(org.apache.directory.studio.ldapbrowser.core.model.IValue) + */ + public Object getRawValue( IValue value ) + { + Object o = super.getRawValue( value ); + if ( o != null && o instanceof String ) + { + IBrowserConnection connection = value.getAttribute().getEntry().getBrowserConnection(); + LdapDN dn = value.getAttribute().getEntry().getDn(); + return new SubtreeSpecificationValueWrapper( connection, dn, value.getStringValue() ); + } + + return null; + } + + + /** + * The SubtreeSpecificationValueWrapper is used to pass contextual + * information to the opened SubtreeSpecificationDialog. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ + private class SubtreeSpecificationValueWrapper + { + /** The connection, used in DnDialog to browse for an entry */ + private IBrowserConnection connection; + + /** The subentry's DN */ + private LdapDN subentryDN; + + /** The subtreeSpecification */ + private String subtreeSpecification; + + + /** + * Creates a new instance of SubtreeSpecificationValueWrapper. + * + * @param connection + * the connection + * @param subentryDn + * the DN of the subentry + * @param subtreeSpecification + * the subtreeSpecification + */ + private SubtreeSpecificationValueWrapper( IBrowserConnection connection, LdapDN subentryDN, String subtreeSpecification ) + { + this.connection = connection; + this.subentryDN = subentryDN; + this.subtreeSpecification = subtreeSpecification; + } + + + /** + * {@inheritDoc} + */ + public String toString() + { + return subtreeSpecification == null ? "" : subtreeSpecification; //$NON-NLS-1$ + } + + } +} Propchange: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/SubtreeValueEditor.java ------------------------------------------------------------------------------ svn:eol-style = native Added: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/package-info.java URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/package-info.java?rev=592011&view=auto ============================================================================== --- directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/package-info.java (added) +++ directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/package-info.java Mon Nov 5 06:27:47 2007 @@ -0,0 +1,23 @@ +/* + * 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. + * + */ +/** + * Contains all ACI item editor specific inner value editors. + */ +package org.apache.directory.studio.aciitemeditor.valueeditors; \ No newline at end of file Propchange: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/valueeditors/package-info.java ------------------------------------------------------------------------------ svn:eol-style = native Added: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGeneralComposite.java URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGeneralComposite.java?rev=592011&view=auto ============================================================================== --- directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGeneralComposite.java (added) +++ directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGeneralComposite.java Mon Nov 5 06:27:47 2007 @@ -0,0 +1,393 @@ +/* + * 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.aciitemeditor.widgets; + + +import java.util.ArrayList; +import java.util.List; + +import org.apache.directory.shared.ldap.aci.AuthenticationLevel; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.StructuredSelection; +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.TypedEvent; +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.Label; +import org.eclipse.swt.widgets.Spinner; +import org.eclipse.swt.widgets.Text; + + +/** + * This is used to edit general ACI item properties: + *
    + *
  • identification tag + *
  • precedence + *
  • authentication level + *
  • selection for userFirst or itemFirst + *
+ * + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class ACIItemGeneralComposite extends Composite +{ + /** The inner composite for all the content */ + private Composite composite = null; + + /** The identification tag label */ + private Label identificationTagLabel = null; + + /** The identification tag text field */ + private Text identificationTagText = null; + + /** The precedence label */ + private Label precedenceLabel = null; + + /** The spinner to select a valid precedence between 0 and 255 */ + private Spinner precedenceSpinner = null; + + /** The authentication level label */ + private Label authenticationLevelLabel = null; + + /** The combo to select a valid uthentication level */ + private Combo authenticationLevelCombo = null; + + /** + * The combo viewer is attached to authenticationLevelCombo to work with + * AuthenticationLevel objects rather than Strings + */ + private ComboViewer authenticationLevelComboViewer = null; + + /** The user or item first label */ + private Label userOrItemFirstLabel = null; + + /** The user first radio button */ + private Button userFirstRadioButton = null; + + /** The item first radio button */ + private Button itemFirstRadioButton = null; + + /** The list with listers */ + private List listenerList = new ArrayList(); + + + /** + * Creates a new instance of ACIItemGeneralComposite. + * + * @param parent + * @param style + */ + public ACIItemGeneralComposite( Composite parent, int style ) + { + super( parent, style ); + + GridLayout layout = new GridLayout(); + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginHeight = 0; + layout.marginWidth = 0; + setLayout( layout ); + + GridData layoutData = new GridData(); + layoutData.horizontalAlignment = GridData.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.verticalAlignment = GridData.CENTER; + setLayoutData( layoutData ); + + createComposite(); + } + + + /** + * This method initializes composite + * + */ + private void createComposite() + { + + GridData identificationTagGridData = new GridData(); + identificationTagGridData.grabExcessHorizontalSpace = true; + identificationTagGridData.verticalAlignment = GridData.CENTER; + identificationTagGridData.horizontalSpan = 2; + identificationTagGridData.horizontalAlignment = GridData.FILL; + + GridData precedenceGridData = new GridData(); + precedenceGridData.grabExcessHorizontalSpace = true; + precedenceGridData.verticalAlignment = GridData.CENTER; + precedenceGridData.horizontalSpan = 2; + precedenceGridData.horizontalAlignment = GridData.BEGINNING; + precedenceGridData.widthHint = 3 * 12; + + GridData authenticationLevelGridData = new GridData(); + authenticationLevelGridData.grabExcessHorizontalSpace = true; + authenticationLevelGridData.verticalAlignment = GridData.CENTER; + authenticationLevelGridData.horizontalSpan = 2; + authenticationLevelGridData.horizontalAlignment = GridData.FILL; + + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 3; + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + gridData.grabExcessHorizontalSpace = true; + gridData.verticalAlignment = GridData.CENTER; + + composite = new Composite( this, SWT.NONE ); + composite.setLayout( gridLayout ); + composite.setLayoutData( gridData ); + + identificationTagLabel = new Label( composite, SWT.NONE ); + identificationTagLabel.setText( Messages.getString( "ACIItemGeneralComposite.idTag.label" ) ); //$NON-NLS-1$ + identificationTagText = new Text( composite, SWT.BORDER ); + identificationTagText.setLayoutData( identificationTagGridData ); + identificationTagText.addModifyListener( new ModifyListener() + { + public void modifyText( ModifyEvent event ) + { + fire( event ); + } + } ); + + precedenceLabel = new Label( composite, SWT.NONE ); + precedenceLabel.setText( Messages.getString( "ACIItemGeneralComposite.precedence.label" ) ); //$NON-NLS-1$ + precedenceSpinner = new Spinner( composite, SWT.BORDER ); + precedenceSpinner.setMinimum( 0 ); + precedenceSpinner.setMaximum( 255 ); + precedenceSpinner.setDigits( 0 ); + precedenceSpinner.setIncrement( 1 ); + precedenceSpinner.setPageIncrement( 10 ); + precedenceSpinner.setSelection( 0 ); + precedenceSpinner.setLayoutData( precedenceGridData ); + precedenceSpinner.addModifyListener( new ModifyListener() + { + public void modifyText( ModifyEvent event ) + { + fire( event ); + } + } ); + + authenticationLevelLabel = new Label( composite, SWT.NONE ); + authenticationLevelLabel.setText( Messages.getString( "ACIItemGeneralComposite.authLevel.label" ) ); //$NON-NLS-1$ + authenticationLevelCombo = new Combo( composite, SWT.READ_ONLY ); + authenticationLevelCombo.setLayoutData( authenticationLevelGridData ); + AuthenticationLevel[] authenticationLevels = new AuthenticationLevel[3]; + authenticationLevels[0] = AuthenticationLevel.NONE; + authenticationLevels[1] = AuthenticationLevel.SIMPLE; + authenticationLevels[2] = AuthenticationLevel.STRONG; + authenticationLevelComboViewer = new ComboViewer( authenticationLevelCombo ); + authenticationLevelComboViewer.setContentProvider( new ArrayContentProvider() ); + authenticationLevelComboViewer.setLabelProvider( new LabelProvider() ); + authenticationLevelComboViewer.setInput( authenticationLevels ); + authenticationLevelComboViewer.setSelection( new StructuredSelection( AuthenticationLevel.NONE ) ); + authenticationLevelCombo.addModifyListener( new ModifyListener() + { + public void modifyText( ModifyEvent event ) + { + fire( event ); + } + } ); + + userOrItemFirstLabel = new Label( composite, SWT.NONE ); + userOrItemFirstLabel.setText( Messages.getString( "ACIItemGeneralComposite.userOrItemFirst.label" ) ); //$NON-NLS-1$ + userFirstRadioButton = new Button( composite, SWT.RADIO ); + userFirstRadioButton.setText( Messages.getString( "ACIItemGeneralComposite.userFirst.label" ) ); //$NON-NLS-1$ + userFirstRadioButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent event ) + { + fire( event ); + } + } ); + itemFirstRadioButton = new Button( composite, SWT.RADIO ); + itemFirstRadioButton.setText( Messages.getString( "ACIItemGeneralComposite.itemFirst.label" ) ); //$NON-NLS-1$ + itemFirstRadioButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent event ) + { + fire( event ); + } + } ); + + } + + + /** + * Add the listener to the list of listeners. + * + * @param listener + */ + public void addWidgetModifyListener( WidgetModifyListener listener ) + { + checkWidget(); + if ( listener == null ) + SWT.error( SWT.ERROR_NULL_ARGUMENT ); + listenerList.add( listener ); + } + + + /** + * Removes the listener from the list of listeners. + * + * @param listener + */ + public void removeWidgetModifyListener( WidgetModifyListener listener ) + { + checkWidget(); + if ( listener == null ) + SWT.error( SWT.ERROR_NULL_ARGUMENT ); + listenerList.remove( listener ); + } + + + /** + * Fires WidgetModifyEvents. + * + * @param event the original event + */ + private void fire( TypedEvent event ) + { + for ( WidgetModifyListener listener : listenerList ) + { + listener.widgetModified( new WidgetModifyEvent( this ) ); + } + } + + + /** + * Returns the identification tag. + * + * @return the identification tag + */ + public String getIdentificationTag() + { + return identificationTagText.getText(); + } + + + /** + * Sets the identification tag + * + * @param identificationTag the identification tag + */ + public void setIdentificationTag( String identificationTag ) + { + identificationTagText.setText( identificationTag ); + } + + + /** + * Returns the selected precedence. + * + * @return the selected precedence + */ + public int getPrecedence() + { + return precedenceSpinner.getSelection(); + } + + + /** + * Sets the precedence + * + * @param precedence the precedence + */ + public void setPrecedence( int precedence ) + { + precedenceSpinner.setSelection( precedence ); + } + + + /** + * Returns the selected authentication level. + * + * @return the selected authentication level + */ + public AuthenticationLevel getAuthenticationLevel() + { + IStructuredSelection selection = ( IStructuredSelection ) authenticationLevelComboViewer.getSelection(); + return ( AuthenticationLevel ) selection.getFirstElement(); + } + + + /** + * Sets the authentication level. + * + * @param authenticationLevel the authentication level + */ + public void setAuthenticationLevel( AuthenticationLevel authenticationLevel ) + { + IStructuredSelection selection = new StructuredSelection( authenticationLevel ); + authenticationLevelComboViewer.setSelection( selection ); + } + + + /** + * Returns true if user first is selected. + * + * @return true if user first is selected + */ + public boolean isUserFirst() + { + return userFirstRadioButton.getSelection(); + } + + + /** + * Selects user first. + */ + public void setUserFirst() + { + userFirstRadioButton.setSelection( true ); + itemFirstRadioButton.setSelection( false ); + } + + + /** + * Returns true if item first is selected. + * + * @return true if item first is selected + */ + public boolean isItemFirst() + { + return itemFirstRadioButton.getSelection(); + } + + + /** + * Selects item first. + */ + public void setItemFirst() + { + itemFirstRadioButton.setSelection( true ); + userFirstRadioButton.setSelection( false ); + } + +} Propchange: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGeneralComposite.java ------------------------------------------------------------------------------ svn:eol-style = native Added: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGrantsAndDenialsComposite.java URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGrantsAndDenialsComposite.java?rev=592011&view=auto ============================================================================== --- directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGrantsAndDenialsComposite.java (added) +++ directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGrantsAndDenialsComposite.java Mon Nov 5 06:27:47 2007 @@ -0,0 +1,780 @@ +/* + * 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.aciitemeditor.widgets; + + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.apache.directory.shared.ldap.aci.GrantAndDenial; +import org.apache.directory.studio.aciitemeditor.Activator; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.CheckboxCellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; + + +/** + * This composite contains GUI elements to edit ACI item grants and denials. + + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ +public class ACIItemGrantsAndDenialsComposite extends Composite +{ + + /** The description label */ + private Label label = null; + + /** The tree control for the tree viewer */ + private Tree tree = null; + + /** The tree viewer containing all grants and denials */ + private TreeViewer treeViewer = null; + + /** The composite containing the buttons */ + private Composite buttonComposite = null; + + /** The grant all button */ + private Button grantAllButton = null; + + /** The deny all button */ + private Button denyAllButton = null; + + /** The deselect all button */ + private Button deselectAllButton = null; + + /** The undo button */ + private Button undoButton = null; + + /** The redo button */ + private Button redoButton = null; + + /** Colum 1 */ + private static String PERMISSION = Messages.getString( "ACIItemGrantsAndDenialsComposite.column1.header" ); //$NON-NLS-1$ + + /** Colum2 */ + private static String STATE = Messages.getString( "ACIItemGrantsAndDenialsComposite.column2.header" ); //$NON-NLS-1$ + + /** The colums */ + private static String[] COLUMNS = new String[] + { PERMISSION, STATE }; + + /** The undo/redo stack size */ + private static final int MAX_STACK_SIZE = 25; + + /** Used as input for the tree viewer */ + private GrantAndDenialCategory[] grantAndDenialCategories = new GrantAndDenialCategory[] + { + new GrantAndDenialCategory( + Messages.getString( "ACIItemGrantsAndDenialsComposite.category.read" ), true, new GrantAndDenialWrapper[] //$NON-NLS-1$ + { + new GrantAndDenialWrapper( GrantAndDenial.GRANT_BROWSE, GrantAndDenial.DENY_BROWSE ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_READ, GrantAndDenial.DENY_READ ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_COMPARE, GrantAndDenial.DENY_COMPARE ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_FILTER_MATCH, GrantAndDenial.DENY_FILTER_MATCH ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_RETURN_DN, GrantAndDenial.DENY_RETURN_DN ) } ), + new GrantAndDenialCategory( + Messages.getString( "ACIItemGrantsAndDenialsComposite.category.modify" ), true, new GrantAndDenialWrapper[] //$NON-NLS-1$ + { new GrantAndDenialWrapper( GrantAndDenial.GRANT_ADD, GrantAndDenial.DENY_ADD ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_MODIFY, GrantAndDenial.DENY_MODIFY ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_REMOVE, GrantAndDenial.DENY_REMOVE ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_RENAME, GrantAndDenial.DENY_RENAME ) } ), + new GrantAndDenialCategory( + Messages.getString( "ACIItemGrantsAndDenialsComposite.category.advanced" ), false, new GrantAndDenialWrapper[] //$NON-NLS-1$ + { + new GrantAndDenialWrapper( GrantAndDenial.GRANT_EXPORT, GrantAndDenial.DENY_EXPORT ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_IMPORT, GrantAndDenial.DENY_IMPORT ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_INVOKE, GrantAndDenial.DENY_INVOKE ), + new GrantAndDenialWrapper( GrantAndDenial.GRANT_DISCLOSE_ON_ERROR, + GrantAndDenial.DENY_DISCLOSE_ON_ERROR ) } ) }; + + /** + * A GrantAndDenialCategory is used to categorize grants and denials in a tree. + */ + private class GrantAndDenialCategory + { + /** The category name, displayed in tree */ + private String name; + + /** The initial expanded state */ + private boolean expanded; + + /** The grants and denials wrappers display under this category */ + private GrantAndDenialWrapper[] grantAndDenialWrappers; + + + /** + * Creates a new instance of GrantAndDenialCategory. + * + * @param name the category name, displayed in tree + * @param expanded true if category should be initially expanded + * @param grantAndDenialWrappers the grants and denials wrappers display under this category + */ + private GrantAndDenialCategory( String name, boolean expanded, GrantAndDenialWrapper[] grantAndDenialWrappers ) + { + this.name = name; + this.expanded = expanded; + this.grantAndDenialWrappers = grantAndDenialWrappers; + } + } + + /** + * A GrantAndDenialWrapper is used to display grants and denials in tree and to + * track the current state (not specified, grant or deny). Additional it provides + * undo/redo functionality. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ + private class GrantAndDenialWrapper + { + /** The grant */ + private GrantAndDenial grant; + + /** The denial */ + private GrantAndDenial denial; + + /** The current state: null=not specified, grant or denial */ + private GrantAndDenial activeGrantAndDenial; + + /** List containing previous states of activeGrandAndDenial */ + private List undoStack; + + /** List containing "future" states of activeGrandAndDenial */ + private List redoStack; + + + /** + * Creates a new instance of GrantAndDenialWrapper. + * + * @param grant + * @param denial + */ + private GrantAndDenialWrapper( GrantAndDenial grant, GrantAndDenial denial ) + { + this.grant = grant; + this.denial = denial; + this.activeGrantAndDenial = null; + undoStack = new LinkedList(); + redoStack = new LinkedList(); + } + } + + + /** + * Creates a new instance of ACIItemGrantsAndDenialsComposite. + * + * @param parent + * @param style + */ + public ACIItemGrantsAndDenialsComposite( Composite parent, int style ) + { + super( parent, style ); + + GridLayout layout = new GridLayout(); + layout.makeColumnsEqualWidth = false; + layout.numColumns = 2; + setLayout( layout ); + + GridData layoutData = new GridData(); + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = true; + layoutData.horizontalAlignment = GridData.FILL; + layoutData.verticalAlignment = GridData.FILL; + setLayoutData( layoutData ); + + GridData labelGridData = new GridData(); + labelGridData.horizontalSpan = 2; + labelGridData.verticalAlignment = GridData.CENTER; + labelGridData.grabExcessHorizontalSpace = true; + labelGridData.horizontalAlignment = GridData.FILL; + + label = new Label( this, SWT.NONE ); + label.setText( Messages.getString( "ACIItemGrantsAndDenialsComposite.description" ) ); //$NON-NLS-1$ + label.setLayoutData( labelGridData ); + + createTree(); + + createButtonComposite(); + } + + + /** + * This method initializes tree + * + */ + private void createTree() + { + GridData tableGridData = new GridData( GridData.FILL_BOTH ); + tableGridData.grabExcessHorizontalSpace = true; + tableGridData.grabExcessVerticalSpace = true; + tableGridData.verticalAlignment = GridData.FILL; + tableGridData.horizontalAlignment = GridData.FILL; + //tableGridData.heightHint = 100; + + tree = new Tree( this, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION + | SWT.HIDE_SELECTION ); + tree.setHeaderVisible( true ); + tree.setLayoutData( tableGridData ); + tree.setLinesVisible( true ); + + TreeColumn c1 = new TreeColumn( tree, SWT.LEFT, 0 ); + c1.setText( COLUMNS[0] ); + c1.setWidth( 160 ); + TreeColumn c2 = new TreeColumn( tree, SWT.LEFT, 1 ); + c2.setText( COLUMNS[1] ); + c2.setWidth( 80 ); + // TreeColumn c3 = new TreeColumn( tree, SWT.LEFT, 2 ); + // c3.setText( " " ); //$NON-NLS-1$ + // c3.setWidth( 0 ); + + treeViewer = new TreeViewer( tree ); + treeViewer.setUseHashlookup( true ); + + treeViewer.setColumnProperties( COLUMNS ); + + ICellModifier cellModifier = new GrantsAndDenialsCellModifier(); + treeViewer.setCellModifier( cellModifier ); + CellEditor[] cellEditors = new CellEditor[] + { null, new CheckboxCellEditor( tree ), null }; + treeViewer.setCellEditors( cellEditors ); + + treeViewer.setContentProvider( new GrantsAndDenialsContentProvider() ); + treeViewer.setLabelProvider( new GrantsAndDenialsLabelProvider() ); + treeViewer.setInput( grantAndDenialCategories ); + + // set expanded state + List expandedList = new ArrayList(); + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + if ( grantAndDenialCategory.expanded ) + { + expandedList.add( grantAndDenialCategory ); + } + } + treeViewer.setExpandedElements( expandedList.toArray() ); + } + + + /** + * This method initializes buttonComposite + * + */ + private void createButtonComposite() + { + GridData deselectAllButtonGridData = new GridData(); + deselectAllButtonGridData.horizontalAlignment = GridData.FILL; + deselectAllButtonGridData.grabExcessHorizontalSpace = false; + deselectAllButtonGridData.verticalAlignment = GridData.BEGINNING; + deselectAllButtonGridData.widthHint = Activator.getButtonWidth( this ); + + GridData denyAllButtonGridData = new GridData(); + denyAllButtonGridData.horizontalAlignment = GridData.FILL; + denyAllButtonGridData.grabExcessHorizontalSpace = false; + denyAllButtonGridData.verticalAlignment = GridData.BEGINNING; + denyAllButtonGridData.widthHint = Activator.getButtonWidth( this ); + + GridData grantAllButtonGridData = new GridData(); + grantAllButtonGridData.horizontalAlignment = GridData.FILL; + grantAllButtonGridData.grabExcessHorizontalSpace = false; + grantAllButtonGridData.verticalAlignment = GridData.BEGINNING; + grantAllButtonGridData.widthHint = Activator.getButtonWidth( this ); + + GridData undoButtonGridData = new GridData(); + undoButtonGridData.horizontalAlignment = GridData.FILL; + undoButtonGridData.grabExcessHorizontalSpace = false; + undoButtonGridData.verticalAlignment = GridData.BEGINNING; + undoButtonGridData.widthHint = Activator.getButtonWidth( this ); + + GridData redoButtonGridData = new GridData(); + redoButtonGridData.horizontalAlignment = GridData.FILL; + redoButtonGridData.grabExcessHorizontalSpace = false; + redoButtonGridData.verticalAlignment = GridData.BEGINNING; + redoButtonGridData.widthHint = Activator.getButtonWidth( this ); + + GridLayout gridLayout = new GridLayout(); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.CENTER; + gridData.grabExcessHorizontalSpace = false; + gridData.grabExcessVerticalSpace = false; + gridData.verticalAlignment = GridData.FILL; + + buttonComposite = new Composite( this, SWT.NONE ); + buttonComposite.setLayoutData( gridData ); + buttonComposite.setLayout( gridLayout ); + + grantAllButton = new Button( buttonComposite, SWT.NONE ); + grantAllButton.setText( Messages.getString( "ACIItemGrantsAndDenialsComposite.grantAll.button" ) ); //$NON-NLS-1$ + grantAllButton.setLayoutData( grantAllButtonGridData ); + grantAllButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + backup(); + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.grant; + } + } + treeViewer.refresh(); + } + } ); + + denyAllButton = new Button( buttonComposite, SWT.NONE ); + denyAllButton.setText( Messages.getString( "ACIItemGrantsAndDenialsComposite.denyAll.button" ) ); //$NON-NLS-1$ + denyAllButton.setLayoutData( denyAllButtonGridData ); + denyAllButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + backup(); + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.denial; + } + } + treeViewer.refresh(); + } + } ); + + deselectAllButton = new Button( buttonComposite, SWT.NONE ); + deselectAllButton.setText( Messages.getString( "ACIItemGrantsAndDenialsComposite.deselectAll.button" ) ); //$NON-NLS-1$ + deselectAllButton.setLayoutData( deselectAllButtonGridData ); + deselectAllButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + backup(); + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + grantAndDenialWrapper.activeGrantAndDenial = null; + } + } + treeViewer.refresh(); + } + } ); + + undoButton = new Button( buttonComposite, SWT.NONE ); + undoButton.setText( Messages.getString( "ACIItemGrantsAndDenialsComposite.undo.button" ) ); //$NON-NLS-1$ + undoButton.setLayoutData( undoButtonGridData ); + undoButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + undo(); + treeViewer.refresh(); + } + } ); + undoButton.setEnabled( false ); + + redoButton = new Button( buttonComposite, SWT.NONE ); + redoButton.setText( Messages.getString( "ACIItemGrantsAndDenialsComposite.redo.button" ) ); //$NON-NLS-1$ + redoButton.setLayoutData( redoButtonGridData ); + redoButton.addSelectionListener( new SelectionAdapter() + { + public void widgetSelected( SelectionEvent e ) + { + redo(); + treeViewer.refresh(); + } + } ); + redoButton.setEnabled( false ); + + } + + /** + * The ICellModifier user for this tree viewer. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ + private class GrantsAndDenialsCellModifier implements ICellModifier + { + + /** + * Only GrantAndDenialWrappers and the STATE colum is modifyable. + * + * @param element the element + * @param property the property + * + * @return true, if can modify + */ + public boolean canModify( Object element, String property ) + { + if ( element instanceof GrantAndDenialWrapper ) + { + return property.equals( STATE ); + } + + return false; + } + + + /** + * The used CheckboxCellEditor accepts only Booleans. + * + * @param element the element + * @param property the property + * + * @return the value + */ + public Object getValue( Object element, String property ) + { + if ( element instanceof GrantAndDenialWrapper ) + { + if ( property.equals( STATE ) ) + { + return new Boolean( true ); + } + } + + return null; + } + + + /** + * Performs the tree-state transtion. + * + * @param element the element + * @param value the value + * @param property the property + */ + public void modify( Object element, String property, Object value ) + { + if ( element != null && element instanceof Item ) + { + element = ( ( Item ) element ).getData(); + } + + if ( element instanceof GrantAndDenialWrapper ) + { + GrantAndDenialWrapper grantAndDenialWrapper = ( GrantAndDenialWrapper ) element; + + if ( property.equals( STATE ) ) + { + backup(); + if ( grantAndDenialWrapper.activeGrantAndDenial == null ) + { + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.grant; + } + else if ( grantAndDenialWrapper.activeGrantAndDenial == grantAndDenialWrapper.grant ) + { + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.denial; + } + else if ( grantAndDenialWrapper.activeGrantAndDenial == grantAndDenialWrapper.denial ) + { + grantAndDenialWrapper.activeGrantAndDenial = null; + } + } + } + + treeViewer.refresh(); + } + + } + + /** + * The content provider used for this tree viewer. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ + private class GrantsAndDenialsContentProvider extends ArrayContentProvider implements ITreeContentProvider + { + + /** + * Only GrantAndDenialCategories have children. + * + * @param parentElement the parent element + * + * @return the children + */ + public Object[] getChildren( Object parentElement ) + { + if ( parentElement instanceof GrantAndDenialCategory ) + { + GrantAndDenialCategory cat = ( GrantAndDenialCategory ) parentElement; + return cat.grantAndDenialWrappers; + } + + return null; + } + + + /** + * Not used. + * + * @param element the element + * + * @return the parent + */ + public Object getParent( Object element ) + { + return null; + } + + + /** + * Only GrantAndDenialCategories have children. + * + * @param element the element + * + * @return true, if has children + */ + public boolean hasChildren( Object element ) + { + return ( element instanceof GrantAndDenialCategory ); + } + + } + + /** + * The label provider used for this tree viewer. + * + * @author Apache Directory Project + * @version $Rev$, $Date$ + */ + private class GrantsAndDenialsLabelProvider extends LabelProvider implements ITableLabelProvider + { + + /** + * The STATE is displayed as image. + * + * @param element the element + * @param columnIndex the column index + * + * @return the column image + */ + public Image getColumnImage( Object element, int columnIndex ) + { + if ( element instanceof GrantAndDenialWrapper ) + { + GrantAndDenialWrapper grantAndDenialWrapper = ( GrantAndDenialWrapper ) element; + switch ( columnIndex ) + { + case 0: + return null; + case 1: + if ( grantAndDenialWrapper.activeGrantAndDenial == null ) + { + return Activator.getDefault().getImage( + Messages.getString( "ACIItemGrantsAndDenialsComposite.unspecified.icon" ) ); //$NON-NLS-1$ + } + else if ( grantAndDenialWrapper.activeGrantAndDenial == grantAndDenialWrapper.grant ) + { + return Activator.getDefault().getImage( + Messages.getString( "ACIItemGrantsAndDenialsComposite.grant.icon" ) ); //$NON-NLS-1$ + } + else if ( grantAndDenialWrapper.activeGrantAndDenial == grantAndDenialWrapper.denial ) + { + return Activator.getDefault().getImage( + Messages.getString( "ACIItemGrantsAndDenialsComposite.deny.icon" ) ); //$NON-NLS-1$ + } + case 2: + return null; + } + } + return null; + } + + + /** + * Returns GrantAndDenialCategory name or the MicroOperation name. + * + * @param element the element + * @param columnIndex the column index + * + * @return the column text + */ + public String getColumnText( Object element, int columnIndex ) + { + if ( element instanceof GrantAndDenialCategory ) + { + if ( columnIndex == 0 ) + { + GrantAndDenialCategory cat = ( GrantAndDenialCategory ) element; + return cat.name; + } + } + else if ( element instanceof GrantAndDenialWrapper ) + { + if ( columnIndex == 0 ) + { + GrantAndDenialWrapper wrapper = ( GrantAndDenialWrapper ) element; + return wrapper.grant.getMicroOperation().getName(); + } + } + + return ""; //$NON-NLS-1$ + } + + } + + + /** + * Sets the grants and denials. + * + * @param grantsAndDenials + */ + public void setGrantsAndDenials( Collection grantsAndDenials ) + { + for ( GrantAndDenial grantAndDenial : grantsAndDenials ) + { + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + if ( grantAndDenialWrapper.grant == grantAndDenial ) + { + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.grant; + } + else if ( grantAndDenialWrapper.denial == grantAndDenial ) + { + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.denial; + } + } + } + } + + treeViewer.refresh(); + } + + + /** + * Returns the grants and denials as selected by the user. + * + * @return the grants and denials + * @throws ParseException + */ + public Collection getGrantsAndDenials() throws ParseException + { + Collection grantsAndDenials = new ArrayList(); + + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + if ( grantAndDenialWrapper.activeGrantAndDenial != null ) + { + grantsAndDenials.add( grantAndDenialWrapper.activeGrantAndDenial ); + } + } + } + + return grantsAndDenials; + } + + + /** + * Undos the last modification. + */ + private void undo() + { + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + if ( grantAndDenialWrapper.undoStack.size() > 0 ) + { + grantAndDenialWrapper.redoStack.add( 0, grantAndDenialWrapper.activeGrantAndDenial ); + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.undoStack.remove( 0 ); + } + + undoButton.setEnabled( !grantAndDenialWrapper.undoStack.isEmpty() ); + redoButton.setEnabled( !grantAndDenialWrapper.redoStack.isEmpty() ); + } + } + } + + + /** + * Redos the last modification + */ + private void redo() + { + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + if ( grantAndDenialWrapper.redoStack.size() > 0 ) + { + grantAndDenialWrapper.undoStack.add( 0, grantAndDenialWrapper.activeGrantAndDenial ); + grantAndDenialWrapper.activeGrantAndDenial = grantAndDenialWrapper.redoStack.remove( 0 ); + } + + undoButton.setEnabled( !grantAndDenialWrapper.undoStack.isEmpty() ); + redoButton.setEnabled( !grantAndDenialWrapper.redoStack.isEmpty() ); + } + } + } + + + /** + * Saves the current state to the undo stack. + */ + private void backup() + { + for ( GrantAndDenialCategory grantAndDenialCategory : grantAndDenialCategories ) + { + for ( GrantAndDenialWrapper grantAndDenialWrapper : grantAndDenialCategory.grantAndDenialWrappers ) + { + if ( grantAndDenialWrapper.undoStack.size() == MAX_STACK_SIZE ) + { + grantAndDenialWrapper.undoStack.remove( grantAndDenialWrapper.undoStack.size() - 1 ); + } + grantAndDenialWrapper.undoStack.add( 0, grantAndDenialWrapper.activeGrantAndDenial ); + grantAndDenialWrapper.redoStack.clear(); + + undoButton.setEnabled( !grantAndDenialWrapper.undoStack.isEmpty() ); + redoButton.setEnabled( !grantAndDenialWrapper.redoStack.isEmpty() ); + } + } + } + +} Propchange: directory/sandbox/felixk/studio-aciitemeditor/src/main/java/org/apache/directory/studio/aciitemeditor/widgets/ACIItemGrantsAndDenialsComposite.java ------------------------------------------------------------------------------ svn:eol-style = native