org.apache.directory.studio.ldapbrowser.common.wizards.NewEntryDnWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.directory.studio.ldapbrowser.common.wizards.NewEntryDnWizardPage.java

Source

/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */

package org.apache.directory.studio.ldapbrowser.common.wizards;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.lang.ArrayUtils;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.name.Ava;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
import org.apache.directory.studio.common.ui.widgets.WidgetModifyEvent;
import org.apache.directory.studio.common.ui.widgets.WidgetModifyListener;
import org.apache.directory.studio.connection.ui.RunnableContextRunner;
import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator;
import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants;
import org.apache.directory.studio.ldapbrowser.common.widgets.DnBuilderWidget;
import org.apache.directory.studio.ldapbrowser.common.widgets.ListContentProposalProvider;
import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry;
import org.apache.directory.studio.ldapbrowser.core.jobs.ReadEntryRunnable;
import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
import org.apache.directory.studio.ldapbrowser.core.model.IEntry;
import org.apache.directory.studio.ldapbrowser.core.model.IValue;
import org.apache.directory.studio.ldapbrowser.core.model.impl.Attribute;
import org.apache.directory.studio.ldapbrowser.core.model.impl.DummyEntry;
import org.apache.directory.studio.ldapbrowser.core.model.impl.Value;
import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;

/**
 * The NewEntryDnWizardPage is used to compose the new entry's 
 * distinguished name.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class NewEntryDnWizardPage extends WizardPage implements WidgetModifyListener {

    /** The wizard. */
    private NewEntryWizard wizard;

    /** The Dn builder widget. */
    private DnBuilderWidget dnBuilderWidget;

    /** The context entry Dn combo. */
    private Combo contextEntryDnCombo;

    /** The content proposal adapter for the context entry Dn combo. */
    private ContentProposalAdapter contextEntryDnComboCPA;

    /**
     * Creates a new instance of NewEntryDnWizardPage.
     * 
     * @param pageName the page name
     * @param wizard the wizard
     */
    public NewEntryDnWizardPage(String pageName, NewEntryWizard wizard) {
        super(pageName);
        setTitle(Messages.getString("NewEntryDnWizardPage.DistinguishedName")); //$NON-NLS-1$
        if (wizard.isNewContextEntry()) {
            setDescription(Messages.getString("NewEntryDnWizardPage.EnterDN")); //$NON-NLS-1$
        } else {
            setDescription(Messages.getString("NewEntryDnWizardPage.SelectParent")); //$NON-NLS-1$
        }
        setImageDescriptor(
                BrowserCommonActivator.getDefault().getImageDescriptor(BrowserCommonConstants.IMG_ENTRY_WIZARD));
        setPageComplete(false);

        this.wizard = wizard;
    }

    /**
     * {@inheritDoc}
     */
    public void dispose() {
        if (dnBuilderWidget != null) {
            dnBuilderWidget.removeWidgetModifyListener(this);
            dnBuilderWidget.dispose();
            dnBuilderWidget = null;
        }
        super.dispose();
    }

    /**
     * Validates the input fields.
     */
    private void validate() {
        if (wizard.isNewContextEntry() && !"".equals(contextEntryDnCombo.getText()) //$NON-NLS-1$
                && Dn.isValid(contextEntryDnCombo.getText())) {
            setPageComplete(true);
            saveState();
        } else if (!wizard.isNewContextEntry() && dnBuilderWidget.getRdn() != null
                && dnBuilderWidget.getParentDn() != null) {
            setPageComplete(true);
            saveState();
        } else {
            setPageComplete(false);
        }
    }

    /**
     * Initializes the Dn builder widget with the Dn of
     * the prototype entry. Called when this page becomes visible.
     */
    private void loadState() {
        DummyEntry newEntry = wizard.getPrototypeEntry();

        if (wizard.isNewContextEntry()) {
            IAttribute attribute = wizard.getSelectedConnection().getRootDSE()
                    .getAttribute(SchemaConstants.NAMING_CONTEXTS_AT);
            if (attribute != null) {
                String[] values = attribute.getStringValues();

                // content proposals
                contextEntryDnComboCPA.setContentProposalProvider(new ListContentProposalProvider(values));

                // fill namingContext values into combo 
                contextEntryDnCombo.setItems(values);

                // preset combo text
                if (Arrays.asList(values).contains(newEntry.getDn().getName())) {
                    contextEntryDnCombo.setText(newEntry.getDn().getName());
                }
            }
        } else {
            Collection<AttributeType> atds = SchemaUtils.getAllAttributeTypeDescriptions(newEntry);
            String[] attributeNames = SchemaUtils.getNames(atds).toArray(ArrayUtils.EMPTY_STRING_ARRAY);

            Dn parentDn = null;

            boolean hasSelectedEntry = wizard.getSelectedEntry() != null;
            boolean newEntryParentDnNotNullOrEmpty = !Dn.isNullOrEmpty(newEntry.getDn().getParent());

            if (hasSelectedEntry) {
                boolean newEntryDnEqualsSelectedEntryDn = newEntry.getDn()
                        .equals(wizard.getSelectedEntry().getDn());

                if (newEntryDnEqualsSelectedEntryDn && newEntryParentDnNotNullOrEmpty) {
                    parentDn = newEntry.getDn().getParent();
                } else {
                    parentDn = wizard.getSelectedEntry().getDn();
                }
            } else if (newEntryParentDnNotNullOrEmpty) {
                parentDn = newEntry.getDn().getParent();
            }

            Rdn rdn = newEntry.getRdn();

            dnBuilderWidget.setInput(wizard.getSelectedConnection(), attributeNames, rdn, parentDn);
        }
    }

    /**
     * Saves the Dn of the Dn builder widget to the prototype entry.
     */
    private void saveState() {
        DummyEntry newEntry = wizard.getPrototypeEntry();

        try {
            EventRegistry.suspendEventFiringInCurrentThread();

            // remove old Rdn
            if (newEntry.getRdn().size() > 0) {
                Iterator<Ava> atavIterator = newEntry.getRdn().iterator();
                while (atavIterator.hasNext()) {
                    Ava atav = atavIterator.next();
                    IAttribute attribute = newEntry.getAttribute(atav.getType());
                    if (attribute != null) {
                        IValue[] values = attribute.getValues();
                        for (int v = 0; v < values.length; v++) {
                            if (values[v].getStringValue().equals(atav.getValue().getNormalized())) {
                                attribute.deleteValue(values[v]);
                            }
                        }

                        // If we have removed all the values of the attribute,
                        // then we also need to remove this attribute from the
                        // entry.
                        // This test has been added to fix DIRSTUDIO-222
                        if (attribute.getValueSize() == 0) {
                            newEntry.deleteAttribute(attribute);
                        }
                    }
                }
            }

            // set new Dn
            Dn dn;

            if (wizard.isNewContextEntry()) {
                try {
                    dn = new Dn(contextEntryDnCombo.getText());
                } catch (LdapInvalidDnException e) {
                    dn = Dn.EMPTY_DN;
                }
            } else {
                try {
                    dn = dnBuilderWidget.getParentDn().add(dnBuilderWidget.getRdn());
                } catch (LdapInvalidDnException lide) {
                    // Do nothing
                    dn = Dn.EMPTY_DN;
                }
            }
            newEntry.setDn(dn);

            // add new Rdn
            if (dn.getRdn().size() > 0) {
                Iterator<Ava> atavIterator = dn.getRdn().iterator();
                while (atavIterator.hasNext()) {
                    Ava atav = atavIterator.next();
                    IAttribute rdnAttribute = newEntry.getAttribute(atav.getType());
                    if (rdnAttribute == null) {
                        rdnAttribute = new Attribute(newEntry, atav.getType());
                        newEntry.addAttribute(rdnAttribute);
                    }
                    Object rdnValue = atav.getValue().getNormalized();
                    String[] stringValues = rdnAttribute.getStringValues();
                    if (!Arrays.asList(stringValues).contains(rdnValue)) {
                        rdnAttribute.addValue(new Value(rdnAttribute, rdnValue));
                    }
                }
            }

        } finally {
            EventRegistry.resumeEventFiringInCurrentThread();
        }
    }

    /**
     * {@inheritDoc}
     * 
     * This implementation initializes Dn builder widghet with the
     * Dn of the protoype entry.
     */
    public void setVisible(boolean visible) {
        super.setVisible(visible);

        if (visible) {
            loadState();
            validate();

            if (wizard.isNewContextEntry()) {
                contextEntryDnCombo.setFocus();
            }
        }
    }

    /**
     * {@inheritDoc}
     * 
     * This implementation just checks if this page is complete. It 
     * doesn't call {@link #getNextPage()} to avoid unneeded 
     * invokings of {@link ReadEntryRunnable}s.
     */
    @Override
    public boolean canFlipToNextPage() {
        return isPageComplete();
    }

    /**
     * {@inheritDoc}
     * 
     * This implementation invokes a {@link ReadEntryRunnable} to check if an
     * entry with the composed Dn already exists.
     */
    @Override
    public IWizardPage getNextPage() {
        if (!wizard.isNewContextEntry()) {
            dnBuilderWidget.validate();

            Rdn rdn = dnBuilderWidget.getRdn();
            Dn parentDn = dnBuilderWidget.getParentDn();

            try {
                final Dn dn = parentDn.add(rdn);

                // check if parent exists
                ReadEntryRunnable readEntryRunnable1 = new ReadEntryRunnable(wizard.getSelectedConnection(),
                        parentDn);
                RunnableContextRunner.execute(readEntryRunnable1, getContainer(), false);
                IEntry parentEntry = readEntryRunnable1.getReadEntry();

                if (parentEntry == null) {
                    getShell().getDisplay().syncExec(() -> {
                        MessageDialog.openError(getShell(), Messages.getString("NewEntryDnWizardPage.Error"), //$NON-NLS-1$
                                NLS.bind(Messages.getString("NewEntryDnWizardPage.ParentDoesNotExist"), //$NON-NLS-1$
                                        dnBuilderWidget.getParentDn().toString()));
                    });

                    return null;
                }

                // check that new entry does not exists yet 
                ReadEntryRunnable readEntryRunnable2 = new ReadEntryRunnable(wizard.getSelectedConnection(), dn);
                RunnableContextRunner.execute(readEntryRunnable2, getContainer(), false);
                IEntry entry = readEntryRunnable2.getReadEntry();

                if (entry != null) {
                    getShell().getDisplay().syncExec(() -> {
                        MessageDialog.openError(getShell(), Messages.getString("NewEntryDnWizardPage.Error"), //$NON-NLS-1$
                                NLS.bind(Messages.getString("NewEntryDnWizardPage.EntryAlreadyExists"), //$NON-NLS-1$
                                        dn.toString()));
                    });

                    return null;
                }
            } catch (LdapInvalidDnException lide) {
                return null;
            }
        } else {
            try {
                final Dn dn = new Dn(contextEntryDnCombo.getText());

                // check that new entry does not exists yet 
                ReadEntryRunnable readEntryRunnable2 = new ReadEntryRunnable(wizard.getSelectedConnection(), dn);
                RunnableContextRunner.execute(readEntryRunnable2, getContainer(), false);
                IEntry entry = readEntryRunnable2.getReadEntry();
                if (entry != null) {
                    getShell().getDisplay().syncExec(() -> {
                        MessageDialog.openError(getShell(), Messages.getString("NewEntryDnWizardPage.Error"), //$NON-NLS-1$
                                NLS.bind(Messages.getString("NewEntryDnWizardPage.EntryAlreadyExists"), //$NON-NLS-1$
                                        dn.toString()));
                    });

                    return null;
                }
            } catch (LdapInvalidDnException e) {
                return null;
            }
        }

        return super.getNextPage();
    }

    /**
     * {@inheritDoc}
     */
    public void createControl(Composite parent) {
        if (wizard.isNewContextEntry()) {
            // the combo
            Composite composite = BaseWidgetUtils.createColumnContainer(parent, 1, 1);
            contextEntryDnCombo = BaseWidgetUtils.createCombo(composite, ArrayUtils.EMPTY_STRING_ARRAY, 0, 1);
            contextEntryDnCombo.addModifyListener(event -> validate());

            // attach content proposal behavior
            contextEntryDnComboCPA = new ContentProposalAdapter(contextEntryDnCombo, new ComboContentAdapter(),
                    null, null, null);
            contextEntryDnComboCPA.setFilterStyle(ContentProposalAdapter.FILTER_NONE);
            contextEntryDnComboCPA.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);

            setControl(composite);
        } else {
            dnBuilderWidget = new DnBuilderWidget(true, true);
            dnBuilderWidget.addWidgetModifyListener(this);
            Composite composite = dnBuilderWidget.createContents(parent);
            setControl(composite);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void widgetModified(WidgetModifyEvent event) {
        validate();
    }

    /**
     * Saves the dialogs settings.
     */
    public void saveDialogSettings() {
        if (!wizard.isNewContextEntry()) {
            dnBuilderWidget.saveDialogSettings();
        }
    }

}