com.nextep.designer.dbgm.ui.editors.ForeignKeyFormEditor.java Source code

Java tutorial

Introduction

Here is the source code for com.nextep.designer.dbgm.ui.editors.ForeignKeyFormEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2011 neXtep Software and contributors.
 * All rights reserved.
 *
 * This file is part of neXtep designer.
 *
 * NeXtep designer is free software: you can redistribute it 
 * and/or modify it under the terms of the GNU General Public 
 * License as published by the Free Software Foundation, either 
 * version 3 of the License, or any later version.
 *
 * NeXtep designer is distributed in the hope that it will be 
 * useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with neXtep designer.  
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     neXtep Softwares - initial API and implementation
 *******************************************************************************/
package com.nextep.designer.dbgm.ui.editors;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
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.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import com.nextep.datadesigner.dbgm.impl.ForeignKeyConstraint;
import com.nextep.datadesigner.dbgm.model.ConstraintType;
import com.nextep.datadesigner.dbgm.model.ForeignKeyAction;
import com.nextep.datadesigner.dbgm.model.IBasicColumn;
import com.nextep.datadesigner.dbgm.model.IBasicTable;
import com.nextep.datadesigner.dbgm.model.IDatabaseRawObject;
import com.nextep.datadesigner.dbgm.model.IIndex;
import com.nextep.datadesigner.dbgm.model.IKeyConstraint;
import com.nextep.datadesigner.exception.ErrorException;
import com.nextep.datadesigner.exception.InconsistentObjectException;
import com.nextep.datadesigner.model.IElementType;
import com.nextep.datadesigner.model.INamedObject;
import com.nextep.datadesigner.model.IReference;
import com.nextep.designer.core.CorePlugin;
import com.nextep.designer.core.services.ICoreService;
import com.nextep.designer.dbgm.ui.DBGMUIMessages;
import com.nextep.designer.dbgm.ui.factories.ConverterFactory;
import com.nextep.designer.dbgm.ui.factories.ValidatorFactory;
import com.nextep.designer.dbgm.ui.jface.ColumnBindingLabelProvider;
import com.nextep.designer.dbgm.ui.jface.ColumnsContentProvider;
import com.nextep.designer.dbgm.ui.jface.ConstraintsContentProvider;
import com.nextep.designer.dbgm.ui.jface.DbgmLabelProvider;
import com.nextep.designer.dbgm.ui.jface.ForeignKeyColumnsContentProvider;
import com.nextep.designer.dbgm.ui.model.IColumnBinding;
import com.nextep.designer.ui.factories.ImageFactory;
import com.nextep.designer.ui.factories.UIControllerFactory;
import com.nextep.designer.ui.model.ITypedObjectUIController;
import com.nextep.designer.vcs.ui.editors.base.AbstractFormEditor;
import com.nextep.designer.vcs.ui.services.ICommonUIService;

/**
 * The editor for table foreign keys.
 * 
 * @author Christophe Fondacci
 */
public class ForeignKeyFormEditor extends AbstractFormEditor<ForeignKeyConstraint> {

    private static final Log log = LogFactory.getLog(ForeignKeyFormEditor.class);

    private Text nameText, descText, remoteTableText, remoteConstraintText, enforcingIndexText;
    private Button changeRemoteTableButton, changeRemoteConstraintButton, editColumnButton,
            createEnforcingIndexButton;
    private CCombo onUpdateCombo, onDeleteCombo;
    private Table columnsTable;

    private TableViewer columnsViewer;

    public ForeignKeyFormEditor() {
        super(DBGMUIMessages.getString("editor.foreignKey.details"), //$NON-NLS-1$
                DBGMUIMessages.getString("editor.foreignKey.detailsDesc"), true); //$NON-NLS-1$
    }

    @Override
    protected void createControls(final IManagedForm managedForm, FormToolkit toolkit, Composite editor) {
        editor.setLayout(new GridLayout(3, false));

        // Creating the name editor
        toolkit.createLabel(editor, DBGMUIMessages.getString("editor.foreignKey.name")); //$NON-NLS-1$
        nameText = toolkit.createText(editor, "", SWT.BORDER); //$NON-NLS-1$
        nameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));

        // Creating the description editor
        toolkit.createLabel(editor, DBGMUIMessages.getString("editor.foreignKey.desc")); //$NON-NLS-1$
        descText = toolkit.createText(editor, "", SWT.BORDER); //$NON-NLS-1$
        descText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));

        // Creating the remote table editor
        final Link remoteTableLink = new Link(editor, SWT.NONE);
        remoteTableLink.setText(DBGMUIMessages.getString("editor.foreignKey.remoteTableLink")); //$NON-NLS-1$
        remoteTableLink.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                final IKeyConstraint remoteKey = getModel().getRemoteConstraint();
                if (remoteKey != null) {
                    final IBasicTable remoteTable = remoteKey.getConstrainedTable();
                    if (remoteTable != null) {
                        final ITypedObjectUIController controller = UIControllerFactory
                                .getController(IElementType.getInstance(IBasicTable.TYPE_ID));
                        controller.defaultOpen(remoteTable);
                    }
                }
            }
        });
        remoteTableText = toolkit.createText(editor, "", SWT.BORDER); //$NON-NLS-1$
        remoteTableText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        remoteTableText.setEditable(false);
        changeRemoteTableButton = toolkit.createButton(editor, "", SWT.PUSH); //$NON-NLS-1$
        changeRemoteTableButton.setImage(ImageFactory.ICON_EDIT_TINY);
        changeRemoteTableButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                changeRemoteTable(managedForm.getForm().getShell());
            }
        });

        // Creating remote constraint combo
        final Link remoteConstraintLink = new Link(editor, SWT.NONE);
        remoteConstraintLink.setText(DBGMUIMessages.getString("editor.foreignKey.remoteConstraint")); //$NON-NLS-1$
        remoteConstraintLink.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                final IKeyConstraint remoteKey = getModel().getRemoteConstraint();
                if (remoteKey != null) {
                    final ITypedObjectUIController controller = UIControllerFactory.getController(remoteKey);
                    controller.defaultOpen(remoteKey);
                }
            }
        });
        remoteConstraintText = toolkit.createText(editor, "", SWT.BORDER); //$NON-NLS-1$
        remoteConstraintText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        remoteConstraintText.setEditable(false);
        changeRemoteConstraintButton = toolkit.createButton(editor, "", SWT.PUSH); //$NON-NLS-1$
        changeRemoteConstraintButton.setImage(ImageFactory.ICON_EDIT_TINY);
        changeRemoteConstraintButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                changeRemoteConstraint(managedForm.getForm().getShell());
            }
        });

        // Enforcing index
        final Link enforcingIndexLink = new Link(editor, SWT.NONE);
        enforcingIndexLink.setText(DBGMUIMessages.getString("fk.editor.enforcingIndex")); //$NON-NLS-1$
        enforcingIndexLink.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                // Getting current enforcing index
                Collection<IDatabaseRawObject> indexes = getModel().getEnforcingIndex();
                // If existing we open the corresponding editor
                if (indexes != null && !indexes.isEmpty()) {
                    final IDatabaseRawObject index = indexes.iterator().next();
                    UIControllerFactory.getController(index).defaultOpen(index);
                } else {
                    createEnforcingIndex();
                }
            }
        });
        enforcingIndexText = toolkit.createText(editor, "", SWT.BOLD); //$NON-NLS-1$
        enforcingIndexText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        enforcingIndexText.setEditable(false);
        createEnforcingIndexButton = toolkit.createButton(editor, "", SWT.PUSH); //$NON-NLS-1$
        createEnforcingIndexButton.setImage(ImageFactory.ICON_ADD_TINY);
        createEnforcingIndexButton.setText("Create");
        createEnforcingIndexButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                createEnforcingIndex();
            }
        });
        // On update combo
        toolkit.createLabel(editor, DBGMUIMessages.getString("fk.editor.onUpdate")); //$NON-NLS-1$
        onUpdateCombo = new CCombo(editor, SWT.READ_ONLY | SWT.BORDER);
        onUpdateCombo.setLayoutData(new GridData(SWT.NONE, SWT.FILL, false, false, 2, 1));
        toolkit.adapt(onUpdateCombo);
        for (ForeignKeyAction action : ForeignKeyAction.values()) {
            onUpdateCombo.add(action.getLabel());
        }

        // On delete combo
        toolkit.createLabel(editor, DBGMUIMessages.getString("fk.editor.onDelete")); //$NON-NLS-1$
        onDeleteCombo = new CCombo(editor, SWT.READ_ONLY | SWT.BORDER);
        onDeleteCombo.setLayoutData(new GridData(SWT.NONE, SWT.FILL, false, false, 2, 1));
        toolkit.adapt(onDeleteCombo);
        for (ForeignKeyAction action : ForeignKeyAction.values()) {
            onDeleteCombo.add(action.getLabel());
        }

        // Foreign key columns component
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
        gd.heightHint = 200;
        columnsTable = new Table(editor, SWT.FULL_SELECTION | SWT.BORDER);
        toolkit.adapt(columnsTable);
        final TableColumn remoteColumn = new TableColumn(columnsTable, SWT.NONE);
        remoteColumn.setWidth(150);
        remoteColumn.setText(DBGMUIMessages.getString("fk.editor.remoteTableColumns")); //$NON-NLS-1$
        final TableColumn tableColumn = new TableColumn(columnsTable, SWT.NONE);
        tableColumn.setWidth(150);
        tableColumn.setText(DBGMUIMessages.getString("fk.editor.tableColumns")); //$NON-NLS-1$
        columnsTable.setLayoutData(gd);
        columnsTable.setHeaderVisible(true);
        columnsTable.setLinesVisible(true);
        final TableColumn warnColumn = new TableColumn(columnsTable, SWT.NONE);
        warnColumn.setText(DBGMUIMessages.getString("fk.editor.warnings")); //$NON-NLS-1$
        warnColumn.setWidth(200);

        editColumnButton = toolkit.createButton(editor,
                DBGMUIMessages.getString("editor.foreignKey.editColumnButton"), SWT.PUSH); //$NON-NLS-1$
        editColumnButton.setImage(ImageFactory.ICON_EDIT_TINY);
        editColumnButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
        editColumnButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                editSelectedColumn();
            }
        });
        columnsTable.addMouseListener(new MouseListener() {

            @Override
            public void mouseUp(MouseEvent e) {
            }

            @Override
            public void mouseDown(MouseEvent e) {
            }

            @Override
            public void mouseDoubleClick(MouseEvent e) {
                editSelectedColumn();
            }
        });

        columnsViewer = new TableViewer(columnsTable);
        columnsViewer.setContentProvider(new ForeignKeyColumnsContentProvider());
        columnsViewer.setLabelProvider(new ColumnBindingLabelProvider());
        columnsViewer.setInput(getModel());
    }

    /**
     * Prompts the user for the selection of a column to map to the currently selected remote
     * constraint column. After the user has selected a column, it will replace the previously
     * mapped foreign key column.
     */
    private void editSelectedColumn() {
        final ISelection s = columnsViewer.getSelection();
        final int columnIndex = columnsViewer.getTable().getSelectionIndex();
        if (!s.isEmpty() && s instanceof IStructuredSelection) {
            final IStructuredSelection sel = (IStructuredSelection) s;
            final IColumnBinding columnBinding = (IColumnBinding) sel.getFirstElement();
            final IBasicColumn remoteColumn = columnBinding.getColumn();
            final IBasicColumn fkColumn = columnBinding.getAssociatedColumn();
            final ICommonUIService uiService = CorePlugin.getService(ICommonUIService.class);
            final IContentProvider columnsProvider = new ColumnsContentProvider();
            final ILabelProvider labelProvider = new DbgmLabelProvider();
            final ForeignKeyConstraint fk = getModel();

            if (!CorePlugin.getService(ICoreService.class).isLocked(fk)) {
                final IBasicColumn newFkColumn = (IBasicColumn) uiService.findElement(columnsTable.getShell(),
                        MessageFormat.format(DBGMUIMessages.getString("editor.foreignKey.editColumnDlgTitle"), //$NON-NLS-1$
                                remoteColumn.getParent().getName(), remoteColumn.getName()),
                        fk.getConstrainedTable(), columnsProvider, labelProvider);

                // Removing listener on previous column
                if (newFkColumn != null) {
                    // Bug #332: Previous column mapping on this column index may not be defined
                    if (columnIndex >= 0 && fk.getColumns().size() > columnIndex) {
                        final IBasicColumn previousCol = fk.getColumns().get(columnIndex);
                        if (previousCol != null) {
                            fk.removeColumn(previousCol);
                        }
                    }
                    // Adding the constraint (minimum position is 0 when not found before)
                    fk.addConstrainedColumn(Math.max(columnIndex, 0), newFkColumn);
                }
            }
        }
    }

    /**
     * Refreshing current columns mappings from remote constraint to current table columns.
     * 
     * @param guessMappedColumn should this method try to "guess" the foreign key column which
     *        matches remote column
     */
    private void adjustForeignKeyColumns(boolean guessMappedColumn) {
        final ForeignKeyConstraint constraint = getModel();
        final IKeyConstraint currentRemoteConstraint = constraint.getRemoteConstraint();

        if (currentRemoteConstraint != null) {
            final Iterator<IBasicColumn> remoteColIt = currentRemoteConstraint.getColumns().iterator();
            final Iterator<IBasicColumn> fkColIt = new ArrayList<IBasicColumn>(constraint.getColumns()).iterator();
            // Iterating over 2 collection synchronously to :
            // - remove any overflowing fk column
            // - guess any remote constraint column we could match
            while (remoteColIt.hasNext()) {
                final IBasicColumn remoteCol = remoteColIt.next();
                if (fkColIt.hasNext()) {
                    fkColIt.next();
                } else {
                    IBasicColumn guessedCol = null;
                    // Guessing any corresponding column by its name if needed
                    if (guessMappedColumn) {
                        guessedCol = getConstrainedColumn(constraint.getConstrainedTable(), remoteCol.getName());
                    }
                    if (guessedCol == null) {
                        // Forcing inconsistency by setting current col to remote col
                        guessedCol = remoteCol;
                    }
                    constraint.addColumn(guessedCol);
                }
            }
            // Removing any overflowing fk column
            removeSubsequentForeignKeyColumns(fkColIt);
        }
    }

    /**
     * Convenience method to remove from the list of constrained columns of the current foreign key
     * constraint all columns indicated by the specified <code>Iterator</code>.
     * 
     * @param fkColsIt an {@link Iterator} pointing to the {@link IBasicColumn} to remove from the
     *        list of the constrained columns of the current foreign key
     */
    private void removeSubsequentForeignKeyColumns(Iterator<IBasicColumn> fkColsIt) {
        final ForeignKeyConstraint constraint = (ForeignKeyConstraint) getModel();

        while (fkColsIt.hasNext()) {
            IBasicColumn fkCol = fkColsIt.next();
            constraint.removeColumn(fkCol);
        }
    }

    /**
     * Retrieves the constrained column from its name string.
     * 
     * @param constraint constraint which reference the named column
     * @param columnName string value of the column name
     * @return the {@link IBasicColumn} instance
     */
    private IBasicColumn getConstrainedColumn(IBasicTable table, String columnName) {
        for (IBasicColumn c : table.getColumns()) {
            if (c.getName().equals(columnName)) {
                return c;
            }
        }
        return null;
    }

    /**
     * Prompts the user for a new remote table and defines this selection in the current foreign
     * key.
     */
    private void changeRemoteTable(Shell shell) {
        final ICommonUIService uiService = CorePlugin.getService(ICommonUIService.class);
        final IBasicTable remoteTable = (IBasicTable) uiService.findElement(shell,
                DBGMUIMessages.getString("changeRemoteTableTitle"), //$NON-NLS-1$
                IElementType.getInstance(IBasicTable.TYPE_ID));
        if (remoteTable != null) {
            final Collection<IKeyConstraint> constraints = remoteTable.getConstraints();
            updateRemoteConstraint(constraints.toArray(new IKeyConstraint[constraints.size()]));
        } else {
            getModel().setRemoteConstraintRef(null);
            changeRemoteConstraintButton.setEnabled(false);
        }
    }

    /**
     * Prompts the user for a new remote table and defines this selection in the current foreign
     * key.
     */
    private void changeRemoteConstraint(Shell shell) {
        final ICommonUIService uiService = CorePlugin.getService(ICommonUIService.class);
        final IKeyConstraint currentConstraint = getModel().getRemoteConstraint();
        if (currentConstraint != null) {
            final IBasicTable remoteTable = currentConstraint.getConstrainedTable();
            final IKeyConstraint remoteConstraint = (IKeyConstraint) uiService.findElement(shell,
                    DBGMUIMessages.getString("changeRemoteConstraintTitle"), remoteTable, //$NON-NLS-1$
                    new ConstraintsContentProvider(ConstraintType.UNIQUE, ConstraintType.PRIMARY),
                    new DbgmLabelProvider());
            if (remoteConstraint != null) {
                updateRemoteConstraint(remoteConstraint);
            }
        }
    }

    /**
     * Updates the remote constraint of the current foreign key by selecting the first eligible
     * unique or primary key constraint from the provided list. This method will reset the remote
     * constraint when no constraint is provided.
     * 
     * @param constraints a list of eligible constraint
     */
    private void updateRemoteConstraint(IKeyConstraint... constraints) {
        if (constraints == null || constraints.length == 0) {
            // No constraint, emptying current remote constraint
            getModel().setRemoteConstraintRef(null);
        } else {
            // Selecting first eligible unique or primary key
            for (IKeyConstraint constraint : constraints) {
                switch (constraint.getConstraintType()) {
                case UNIQUE:
                case PRIMARY:
                    getModel().setRemoteConstraint(constraint);
                    // Adjusting foreign key columns (making equal size, guessing mapped columns)
                    adjustForeignKeyColumns(true);
                    return;
                }
            }
            // We fall here when no eligible constraint has been selected
            getModel().setRemoteConstraintRef(null);
            // Adjusting foreign key columns (making equal size, guessing mapped columns)
            adjustForeignKeyColumns(true);
        }

    }

    @Override
    protected void doBindModel(DataBindingContext context) {
        IObservableValue selectionValue = ViewersObservables.observeSingleSelection(getSelectionProvider());

        // Binding name
        IObservableValue widgetValue = WidgetProperties.text(SWT.FocusOut).observe(nameText);
        IObservableValue modelValue = PojoObservables.observeDetailValue(selectionValue, "name", //$NON-NLS-1$
                String.class);

        UpdateValueStrategy targetModelStrategy = new UpdateValueStrategy();
        targetModelStrategy.setAfterConvertValidator(ValidatorFactory.createNameValidator(false));
        Binding boundValue = context.bindValue(widgetValue, modelValue, targetModelStrategy, null);
        ControlDecorationSupport.create(boundValue, SWT.TOP | SWT.LEFT);

        // Binding description
        widgetValue = WidgetProperties.text(SWT.FocusOut).observe(descText);
        modelValue = PojoObservables.observeDetailValue(selectionValue, "description", String.class); //$NON-NLS-1$
        boundValue = context.bindValue(widgetValue, modelValue, null, null);

        // Binding on update action
        widgetValue = WidgetProperties.text().observe(onUpdateCombo);
        modelValue = PojoObservables.observeDetailValue(selectionValue, "onUpdateAction", //$NON-NLS-1$
                ForeignKeyAction.class);
        UpdateValueStrategy modelUpdateStrategy = new UpdateValueStrategy();
        modelUpdateStrategy.setConverter(ConverterFactory.createForeignKeyActionModelConverter());
        UpdateValueStrategy targetUpdateStrategy = new UpdateValueStrategy();
        targetUpdateStrategy.setConverter(ConverterFactory.createForeignKeyActionTargetConverter());
        boundValue = context.bindValue(widgetValue, modelValue, modelUpdateStrategy, targetUpdateStrategy);

        // Binding on delete action
        widgetValue = WidgetProperties.text().observe(onDeleteCombo);
        modelValue = PojoObservables.observeDetailValue(selectionValue, "onDeleteAction", //$NON-NLS-1$
                ForeignKeyAction.class);
        modelUpdateStrategy = new UpdateValueStrategy();
        modelUpdateStrategy.setConverter(ConverterFactory.createForeignKeyActionModelConverter());
        targetUpdateStrategy = new UpdateValueStrategy();
        targetUpdateStrategy.setConverter(ConverterFactory.createForeignKeyActionTargetConverter());
        boundValue = context.bindValue(widgetValue, modelValue, modelUpdateStrategy, targetUpdateStrategy);
    }

    @Override
    public void setModel(ForeignKeyConstraint model) {
        super.setModel(model);
        if (columnsViewer != null) {
            columnsViewer.setInput(model);
        }
    }

    @Override
    protected void doRefresh() {
        IKeyConstraint remoteConstraint = null;
        try {
            remoteConstraint = getModel().getRemoteConstraint();
        } catch (ErrorException e) {
            log.error("Error while retrieving FK remote constraint : " + e.getMessage(), e); //$NON-NLS-1$
            remoteConstraint = null;
        }
        if (remoteConstraint != null) {
            remoteTableText.setText(remoteConstraint.getConstrainedTable().getName());
            remoteConstraintText.setText(remoteConstraint.getName());
        } else {
            remoteTableText.setText(""); //$NON-NLS-1$
            remoteConstraintText.setText(""); //$NON-NLS-1$
        }
        // Refreshing enforcing index
        Collection<IDatabaseRawObject> enforcerIndexes = getModel().getEnforcingIndex();
        enforcingIndexText
                .setText(enforcerIndexes.isEmpty() ? DBGMUIMessages.getString("fk.editor.noEnforcingIndex") //$NON-NLS-1$
                        : getCommaSeparatedNames(enforcerIndexes));
        if (enforcerIndexes.isEmpty()) {
            createEnforcingIndexButton.setEnabled(true);
        } else {
            createEnforcingIndexButton.setEnabled(false);
        }

        columnsViewer.refresh();
        remoteTableText.setEditable(false);
        remoteConstraintText.setEditable(false);
        enforcingIndexText.setEditable(false);
    }

    /**
     * Converts the collection of {@link INamedObject} elements into a comma seperated String with
     * the names of all elements, preserving the input ordering.
     * 
     * @param elements a {@link Collection} of {@link INamedObject}
     * @return a comma seperated String with elements names
     */
    private String getCommaSeparatedNames(Collection<? extends INamedObject> elements) {
        if (elements == null) {
            return "";
        }
        StringBuilder buf = new StringBuilder();
        String seperator = "";
        for (INamedObject namedObj : elements) {
            buf.append(seperator + namedObj.getName());
            seperator = ", ";
        }
        return buf.toString();
    }

    /**
     * Creates an enforcing index for the current fk
     */
    private void createEnforcingIndex() {
        final ForeignKeyConstraint fk = getModel();
        try {
            fk.checkConsistency();
        } catch (InconsistentObjectException e) {
            MessageDialog.openWarning(createEnforcingIndexButton.getShell(),
                    "Fix " + fk.getName() + " problems first", "Foreign key '" + fk.getName()
                            + "' has problems. You need to fix those problems before you can create its enforcing index.");
            return;
        }
        IIndex i = (IIndex) UIControllerFactory.getController(IElementType.getInstance(IIndex.INDEX_TYPE))
                .emptyInstance(fk.getName(), fk.getConstrainedTable());
        // i.setIndexedTableRef(c.getConstrainedTable().getReference());
        for (IReference colRef : fk.getConstrainedColumnsRef()) {
            i.addColumnRef(colRef);
        }
        refresh();
    }
}