You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by fe...@apache.org on 2007/11/05 15:28:02 UTC

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...

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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @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<String> 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<String>();
+        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<String> 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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     * @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:
+ * <ul>
+ *   <li>identification tag
+ *   <li>precedence
+ *   <li>authentication level
+ *   <li>selection for userFirst or itemFirst
+ * </ul>
+ * 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @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<WidgetModifyListener> listenerList = new ArrayList<WidgetModifyListener>();
+
+
+    /**
+     * 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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     * @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<GrantAndDenial> undoStack;
+
+        /** List containing "future" states of activeGrandAndDenial */
+        private List<GrantAndDenial> 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<GrantAndDenial>();
+            redoStack = new LinkedList<GrantAndDenial>();
+        }
+    }
+
+
+    /**
+     * 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<GrantAndDenialCategory> expandedList = new ArrayList<GrantAndDenialCategory>();
+        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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     * @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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     * @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 <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     * @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<GrantAndDenial> 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<GrantAndDenial> getGrantsAndDenials() throws ParseException
+    {
+        Collection<GrantAndDenial> grantsAndDenials = new ArrayList<GrantAndDenial>();
+
+        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