/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.relational.ui.edit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.metamodels.relational.PrimaryKey;
import org.teiid.designer.metamodels.relational.UniqueConstraint;
import org.teiid.designer.metamodels.relational.util.RelationalUtil;
import org.teiid.designer.relational.RelationalConstants;
import org.teiid.designer.relational.RelationalConstants.MULTIPLICITY;
import org.teiid.designer.relational.model.RelationalColumn;
import org.teiid.designer.relational.model.RelationalForeignKey;
import org.teiid.designer.relational.model.RelationalTable;
import org.teiid.designer.relational.ui.Messages;
import org.teiid.designer.relational.ui.UiConstants;
import org.teiid.designer.relational.ui.UiPlugin;
import org.teiid.designer.ui.common.UILabelUtil;
import org.teiid.designer.ui.common.UiLabelConstants;
import org.teiid.designer.ui.common.util.WidgetFactory;
import org.teiid.designer.ui.common.util.WidgetUtil;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
*
*/
public class EditForeignKeyDialog extends TitleAreaDialog {
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private final String CREATE_TITLE = Messages.createForeignKeyTitle;
private final String EDIT_TITLE = Messages.editForeignKeyTitle;
private List<String> MULTIPLICITY_LIST;
//=============================================================
// Instance variables
//=============================================================
RelationalForeignKey originalFK;
RelationalForeignKey editedFK;
RelationalTable theTable;
IFile theModelFile;
String selectedTableName;
String selectedKeyOrConstraint;
TableViewer keyViewer;
TableViewer theColumnDataViewer;
Combo uniqueKeyMultiCombo;
Combo foreignKeyMultiCombo;
Button allowJoinButton;
Set<RelationalColumn> selectedColumns = new HashSet<RelationalColumn>();
boolean isEdit;
boolean creatingContents = false;
boolean processingChecks = false;
//=============================================================
// Constructors
//=============================================================
/**
* ParsedDataRowDialog constructor.
*
* @param parent the parent of this dialog
* @param theModelFile the model file
* @param theTable the relational table object
* @param foreignKey the FK being edited
* @param isEdit edit mode
*/
public EditForeignKeyDialog(Shell parent, IFile theModelFile, RelationalTable theTable, RelationalForeignKey foreignKey, boolean isEdit) {
super(parent);
this.theModelFile = theModelFile;
this.theTable = theTable;
this.isEdit = isEdit;
boolean reallyIsEdit = isEdit;
this.originalFK = foreignKey;
if( reallyIsEdit ) {
this.editedFK = this.originalFK.clone();
}
if( !reallyIsEdit ) {
this.editedFK = foreignKey;
}
MULTIPLICITY_LIST = new ArrayList<String>();
for( String str : MULTIPLICITY.AS_ARRAY ) {
MULTIPLICITY_LIST.add(str);
}
}
@Override
protected void configureShell( Shell shell ) {
super.configureShell(shell);
if( isEdit ) {
shell.setText(EDIT_TITLE);
} else {
shell.setText(CREATE_TITLE);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.window.Window#setShellStyle(int)
*/
@Override
protected void setShellStyle( int newShellStyle ) {
super.setShellStyle(newShellStyle | SWT.RESIZE | SWT.MAX);
}
//=============================================================
// Instance methods
//=============================================================
@Override
protected Control createDialogArea(Composite parent) {
creatingContents = true;
if( isEdit ) {
setTitle(EDIT_TITLE);
} else {
setTitle(CREATE_TITLE);
}
Composite dialogComposite = (Composite)super.createDialogArea(parent);
Composite composite = WidgetFactory.createPanel(dialogComposite);
//------------------------------
// Set layout for the Composite
//------------------------------
GridLayout gridLayout = new GridLayout();
composite.setLayout(gridLayout);
gridLayout.numColumns = 2;
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.grabExcessHorizontalSpace = true;
gridData.widthHint = 500;
composite.setLayoutData(gridData);
Label label = new Label(composite, SWT.NONE | SWT.RIGHT);
label.setText(UILabelUtil.getLabel(UiLabelConstants.LABEL_IDS.NAME));
label.setLayoutData(new GridData());
final Text fkNameText = new Text(composite, SWT.BORDER | SWT.SINGLE);
fkNameText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
fkNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fkNameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText( final ModifyEvent event ) {
String value = fkNameText.getText();
if( value == null ) {
value = EMPTY_STRING;
}
editedFK.setName(value);
validate();
}
});
label = new Label(composite, SWT.NONE | SWT.RIGHT);
label.setText(Messages.nameInSourceLabel);
label.setLayoutData(new GridData());
final Text fkNISText = new Text(composite, SWT.BORDER | SWT.SINGLE);
fkNISText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
fkNISText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fkNISText.addModifyListener(new ModifyListener() {
@Override
public void modifyText( final ModifyEvent event ) {
String value = fkNISText.getText();
if( value == null ) {
value = EMPTY_STRING;
}
editedFK.setNameInSource(value);
validate();
}
});
WidgetFactory.createLabel(composite, Messages.foreignKeyMultiplicity);
ILabelProvider multipicityLP = new LabelProvider() {
@Override
public String getText( final Object source ) {
return (String)source;
}
@Override
public Image getImage( final Object source ) {
return null;
}
};
this.foreignKeyMultiCombo = WidgetFactory.createCombo(composite,
SWT.READ_ONLY,
GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_CENTER,
Collections.EMPTY_LIST,
editedFK.getForeignKeyMultiplicity(),
multipicityLP,
true);
this.foreignKeyMultiCombo.setItems(RelationalConstants.MULTIPLICITY.AS_ARRAY);
this.foreignKeyMultiCombo.addModifyListener(new ModifyListener() {
@Override
public void modifyText( final ModifyEvent event ) {
if( foreignKeyMultiCombo.getSelectionIndex() > -1 ) {
editedFK.setForeignKeyMultiplicity(foreignKeyMultiCombo.getItem(foreignKeyMultiCombo.getSelectionIndex()));
validate();
}
}
});
WidgetUtil.setComboItems(this.foreignKeyMultiCombo, MULTIPLICITY_LIST, multipicityLP, true);
WidgetFactory.createLabel(composite, Messages.uniqueKeyMultiplicity);
this.uniqueKeyMultiCombo = WidgetFactory.createCombo(composite,
SWT.READ_ONLY,
GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_CENTER,
Collections.EMPTY_LIST,
editedFK.getPrimaryKeyMultiplicity(),
multipicityLP,
true);
this.uniqueKeyMultiCombo.setItems(RelationalConstants.MULTIPLICITY.AS_ARRAY);
this.uniqueKeyMultiCombo.addModifyListener(new ModifyListener() {
@Override
public void modifyText( final ModifyEvent event ) {
if( uniqueKeyMultiCombo.getSelectionIndex() > -1 ) {
editedFK.setPrimaryKeyMultiplicity(uniqueKeyMultiCombo.getItem(uniqueKeyMultiCombo.getSelectionIndex()));
validate();
}
}
});
WidgetUtil.setComboItems(this.uniqueKeyMultiCombo, MULTIPLICITY_LIST, multipicityLP, true);
this.allowJoinButton = new Button(composite, SWT.CHECK);
this.allowJoinButton.setText(Messages.allowJoinLabel);
this.allowJoinButton.setToolTipText(Messages.allowJoinTooltip);
this.allowJoinButton.setSelection(editedFK.isAllowJoin());
this.allowJoinButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
editedFK.setAllowJoin(allowJoinButton.getSelection());
validate();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
Group keysGroup = WidgetFactory.createGroup(dialogComposite, Messages.selectPrimaryKeyOrUniqueConstraint, SWT.NONE, 2, 2);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 140;
gd.widthHint = 500;
keysGroup.setLayoutData(gd);
Table table = new Table(keysGroup, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.CHECK);
table.setHeaderVisible(false);
table.setLinesVisible(true);
table.setLayout(new TableLayout());
table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
this.keyViewer = new TableViewer(table);
gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 160;
gd.horizontalSpan = 2;
this.keyViewer.getControl().setLayoutData(gd);
this.keyViewer.setContentProvider(new ITreeContentProvider() {
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// NO OP
}
@Override
public void dispose() {
// NO OP
}
@Override
public boolean hasChildren(Object element) {
return true;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public Object[] getElements(Object inputElement) {
if( inputElement instanceof Collection ) {
return ((Collection)inputElement).toArray(new Object[0]);
}
return new Object[0];
}
@Override
public Object[] getChildren(Object parentElement) {
return new Object[0];
}
});
this.keyViewer.setLabelProvider(new ILabelProvider() {
@Override
public void removeListener(ILabelProviderListener listener) {
// NO OP
}
@Override
public boolean isLabelProperty(Object element, String property) {
// NO OP
return false;
}
@Override
public void dispose() {
// NO OP
}
@Override
public void addListener(ILabelProviderListener listener) {
// NO OP
}
@Override
public String getText(Object element) {
String name = EMPTY_STRING;
if( element instanceof UniqueConstraint ) {
name += ((UniqueConstraint)element).getTable().getName();
name += ": " + ((UniqueConstraint)element).getName(); //$NON-NLS-1$
} else {
name += ((PrimaryKey)element).getTable().getName();
name += ": " + ((PrimaryKey)element).getName(); //$NON-NLS-1$
}
return name;
}
@Override
public Image getImage(Object element) {
if( element instanceof UniqueConstraint ) {
return UiPlugin.getDefault().getImage(UiConstants.Images.UC_ICON);
} else if( element instanceof PrimaryKey ){
return UiPlugin.getDefault().getImage(UiConstants.Images.PK_ICON);
}
return null;
}
});
this.keyViewer.getTable().addSelectionListener(
new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if( processingChecks ) {
return;
}
processingChecks = true;
if (e.detail == SWT.CHECK) {
TableItem tableItem = (TableItem) e.item;
boolean wasChecked = tableItem.getChecked();
if( wasChecked ) {
for( TableItem item : keyViewer.getTable().getItems()) {
if( item != tableItem ) {
item.setChecked(false);
}
}
}
}
String tblName = EMPTY_STRING;
String keyName = EMPTY_STRING;
boolean foundCheckedItem = false;
for( TableItem item : keyViewer.getTable().getItems()) {
if( item.getChecked() ) {
foundCheckedItem = true;
EObject selectedKey = (EObject)item.getData();
if( selectedKey instanceof UniqueConstraint ) {
tblName = ((UniqueConstraint)selectedKey).getTable().getName();
keyName = ((UniqueConstraint)selectedKey).getName();
} else {
tblName = ((PrimaryKey)selectedKey).getTable().getName();
keyName = ((PrimaryKey)selectedKey).getName();
}
editedFK.setUniqueKeyName(keyName);
editedFK.setUniqueKeyTableName(tblName);
}
}
if( !foundCheckedItem ) {
editedFK.setUniqueKeyName(keyName);
editedFK.setUniqueKeyTableName(tblName);
}
processingChecks = false;
validate();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
ModelResource mr = ModelUtilities.getModelResource(this.theModelFile);
List keys = new ArrayList();
if( mr != null ) {
try {
keys.addAll(RelationalUtil.findUniqueKeys(mr.getEmfResource()));
} catch (ModelWorkspaceException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
this.keyViewer.setInput(keys);
Group theColumnsGroup = WidgetFactory.createGroup(dialogComposite, Messages.selectColumnReferencesToFK, SWT.NONE, 1, 1);
gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 120;
gd.widthHint = 500;
theColumnsGroup.setLayoutData(gd);
Table tableWidget = new Table(theColumnsGroup, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.CHECK);
table.setHeaderVisible(false);
table.setLinesVisible(true);
table.setLayout(new TableLayout());
table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
theColumnDataViewer = new TableViewer(tableWidget);
gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 160;
gd.horizontalSpan = 2;
theColumnDataViewer.getControl().setLayoutData(gd);
theColumnDataViewer.setContentProvider(new ITreeContentProvider() {
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// TODO Auto-generated method stub
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public boolean hasChildren(Object element) {
return !theTable.getColumns().isEmpty();
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public Object[] getElements(Object inputElement) {
if( inputElement instanceof RelationalTable ) {
return theTable.getColumns().toArray(new Object[0]);
}
return new Object[0];
}
@Override
public Object[] getChildren(Object parentElement) {
// TODO Auto-generated method stub
return new Object[0];
}
});
this.theColumnDataViewer.getTable().addSelectionListener(
new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
editedFK.getColumns().clear();
for( TableItem item : theColumnDataViewer.getTable().getItems() ) {
if( item.getChecked() ) {
editedFK.addColumn((RelationalColumn)item.getData());
}
}
validate();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
theColumnDataViewer.setLabelProvider(new ColumnDataLabelProvider(0));
theColumnDataViewer.setInput(this.theTable);
for( RelationalColumn col : this.editedFK.getColumns() ) {
for( TableItem item : theColumnDataViewer.getTable().getItems() ) {
if( item.getData() == col ) {
item.setChecked(true);
}
}
}
// Set the initial value in the this.keyViewer
if( this.editedFK.getUniqueKeyName() != null && this.editedFK.getUniqueKeyTableName() != null ) {
String name = EMPTY_STRING;
name += this.editedFK.getUniqueKeyTableName();
name += ": " + this.editedFK.getUniqueKeyName(); //$NON-NLS-1$
int index = 0;
int selectedIndex = -1;
for( TableItem item : this.keyViewer.getTable().getItems() ) {
if( item.getData() instanceof EObject ) {
EObject value = (EObject)item.getData();
String keyName = EMPTY_STRING;
if( value instanceof UniqueConstraint ) {
keyName += ((UniqueConstraint)value).getTable().getName();
keyName += ": " + ((UniqueConstraint)value).getName(); //$NON-NLS-1$
} else {
keyName += ((PrimaryKey)value).getTable().getName();
keyName += ": " + ((PrimaryKey)value).getName(); //$NON-NLS-1$
}
if( keyName.equalsIgnoreCase(name) ) {
selectedIndex = index;
item.setChecked(true);
}
}
if( selectedIndex > -1 ) {
break;
}
index++;
}
if( selectedIndex > -1 ) {
this.keyViewer.getTable().select(selectedIndex);
}
}
setMessage(Messages.newForeignKeyMessage);
if( editedFK.getName() != null ) {
fkNameText.setText(editedFK.getName());
}
if( editedFK.getNameInSource() != null ) {
fkNISText.setText(editedFK.getNameInSource());
}
if( editedFK.getForeignKeyMultiplicity() != null ) {
WidgetUtil.setComboText(this.foreignKeyMultiCombo, this.editedFK.getForeignKeyMultiplicity(), multipicityLP);
}
if( editedFK.getPrimaryKeyMultiplicity() != null ) {
WidgetUtil.setComboText(this.uniqueKeyMultiCombo, this.editedFK.getPrimaryKeyMultiplicity(), multipicityLP);
}
creatingContents = false;
return composite;
}
private void validate() {
if( creatingContents ) return;
editedFK.validate();
boolean enable = true;
setMessage(Messages.newForeignKeyMessage);
// ONLY DISABLE if NAME == null
if( editedFK.getName() == null || editedFK.getName().trim().length() == 0 ) {
enable = false;
setErrorMessage(editedFK.getStatus().getMessage());
} else {
if( editedFK.getStatus().getSeverity() < IStatus.ERROR ) {
setErrorMessage(null);
}
if(editedFK.getStatus().getSeverity() == IStatus.WARNING) {
setMessage(editedFK.getStatus().getMessage(), IMessageProvider.WARNING);
} else if(editedFK.getStatus().getSeverity() == IStatus.ERROR) {
setErrorMessage(editedFK.getStatus().getMessage());
}
}
getButton(IDialogConstants.OK_ID).setEnabled(enable);
}
@Override
public void create() {
super.create();
validate();
}
@Override
protected void okPressed() {
if( isEdit ) {
this.originalFK.inject(editedFK);
}
super.okPressed();
}
/**
* @return the table name
*/
public String getTableName() {
return this.selectedTableName;
}
/**
* @return the name of the key or constraint
*/
public String getKeyOrConstraintName() {
return this.selectedKeyOrConstraint;
}
class ColumnDataLabelProvider extends ColumnLabelProvider {
private final int columnNumber;
public ColumnDataLabelProvider(int columnNumber) {
this.columnNumber = columnNumber;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object)
*/
@Override
public String getText(Object element) {
if( element instanceof RelationalColumn ) {
switch (this.columnNumber) {
case 0: {
return ((RelationalColumn)element).getName();
}
case 1: {
return ((RelationalColumn)element).getDatatype();
}
case 2: {
return Integer.toString(((RelationalColumn)element).getLength());
}
}
}
return EMPTY_STRING;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.CellLabelProvider#getToolTipText(java.lang.Object)
*/
@Override
public String getToolTipText(Object element) {
switch (this.columnNumber) {
case 0: {
return "Tooltip 1"; //getString("columnNameColumnTooltip"); //$NON-NLS-1$
}
case 1: {
return "Tooltip 2"; //getString("datatypeColumnTooltip"); //$NON-NLS-1$
}
}
return "unknown tooltip"; //$NON-NLS-1$
}
@Override
public Image getImage(Object element) {
if( this.columnNumber == 0 ) {
return UiPlugin.getDefault().getImage(UiConstants.Images.COLUMN_ICON);
}
return null;
}
}
}