/*******************************************************************************
 * Copyright (c) 2007, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.ui.internal.wizards.gen;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.IPageChangedListener;
import org.eclipse.jface.dialogs.PageChangedEvent;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.jpt.common.ui.internal.util.SWTUtil;
import org.eclipse.jpt.common.ui.internal.util.TableLayoutComposite;
import org.eclipse.jpt.db.Column;
import org.eclipse.jpt.db.Schema;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.gen.internal.Association;
import org.eclipse.jpt.gen.internal.ORMGenCustomizer;
import org.eclipse.jpt.ui.internal.JpaHelpContextIds;
import org.eclipse.swt.SWT;
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.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;


public class JoinColumnsPage extends NewAssociationWizardPage {

	private Label joinColumnsDescLabel1;
	/*the table containing the association columns between table1 and table2
	 * , or table1 and join table if many to many*/
	private TableViewer joinColumnsTable1;
	private ArrayList<SimpleJoin> tableDataModel1 = new ArrayList<SimpleJoin>();  
	private Composite tablesGroup1;
	
	private Label joinColumnsDescLabel2;
	/*the table containing the association columns between join table and table2
	 * if many to many*/
	private TableViewer joinColumnsTable2;
	private ArrayList<SimpleJoin> tableDataModel2 = new ArrayList<SimpleJoin>();  
	private Composite tablesGroup2;
	
	static final String[] JOINCOLUMNS_TABLE_COLUMN_PROPERTIES = { "referrerColumn", "referencedColumn" };
	
	private static final int JOINCOLUMN1_COLUMN_INDEX = 0;
	private static final int JOINCOLUMN2_COLUMN_INDEX = 1;

	protected JoinColumnsPage(ORMGenCustomizer customizer ) {
		super(customizer, "JoinColumnsPage");
		setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_title);
		setDescription(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_desc);
	}

	public void createControl(Composite parent) {
		initializeDialogUnits(parent);
		
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		composite.setLayout(layout);
		this.getHelpSystem().setHelp(composite, JpaHelpContextIds.GENERATE_ENTITIES_WIZARD_JOIN_COLUMNS);

		tablesGroup1 = new Composite(composite, SWT.SHADOW_ETCHED_IN);
		tablesGroup1.setLayoutData(new GridData());
		tablesGroup1.setLayout(new GridLayout(2, false));
		createJoinColumnsTableControl1(tablesGroup1);

		//createMtmJoinColumnsTable2(composite);
		
		setControl(composite);
		this.setPageComplete( false);
		
		((WizardDialog)getContainer()).addPageChangedListener(new IPageChangedListener(){
			public void pageChanged(PageChangedEvent event) {
				if( event.getSelectedPage() == JoinColumnsPage.this ){
					((Composite)JoinColumnsPage.this.getControl()).getParent().layout() ;		
					
				}
			}			
		});
	}

	private void createMtmJoinColumnsTable2(Composite composite) {
		tablesGroup2 = new Composite(composite, SWT.SHADOW_ETCHED_IN);
		tablesGroup2.setLayoutData(new GridData());
		tablesGroup2.setLayout(new GridLayout(2, false));
		createJoinColumnsTableControl2(tablesGroup2);
	}

	/**
	 * Update wizard page UI with new table names
	 */
	@Override
	public void updateWithNewTables() {
		String cardinality = this.getCardinality() ;
		if( Association.MANY_TO_MANY.equals( cardinality ) ){
			updateWithMtmTables();
		}else{
			updateWithOtmTables();
		}
	}

	/**
	 * Update Wizard UI with a single TableViewer with columns from the two associated database tables
	 */
	public void updateWithOtmTables() {
		TableColumn[] columns = joinColumnsTable1.getTable().getColumns();
		String table1Name = this.getReferrerTableName() ;
		String table2Name = this.getReferencedTableName() ;
		
		if( table1Name ==null || table2Name == null )
			return;
		
		columns[0].setText( table1Name );
		columns[1].setText( table2Name );

		//Hide the Join column table 2
		if( tablesGroup2 !=null )
			tablesGroup2.setVisible(false);
		
		tableDataModel1.clear();
		joinColumnsTable1.refresh();
		
		String msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, table1Name, table2Name); 
		joinColumnsDescLabel1.setText(msg);
		joinColumnsDescLabel1.setToolTipText( msg );
		tablesGroup1.layout();
		
		String[] referrerColumnValues = getTableColumns(table1Name);
		String[] referencedColumnValues = getTableColumns(table2Name);
		
		updateCellEditors(joinColumnsTable1, referrerColumnValues, referencedColumnValues);		

		
		((Composite)this.getControl()).layout() ;
	}

	/**
	 * Update Wizard UI with a two TableViewers with the first with columns from table1 to the MTM join table
	 * and the second one with columns from the MTM join table to table2
	 */
	public void updateWithMtmTables() {
		TableColumn[] columns = joinColumnsTable1.getTable().getColumns();
		String table1Name = this.getReferrerTableName() ;
		String table2Name = this.getReferencedTableName() ;
		String joinTableName = this.getJoinTableName() ;
		if( table1Name==null || table2Name==null || joinTableName==null ){
			return;
		}
		if( tablesGroup2 == null ){
			createMtmJoinColumnsTable2( tablesGroup1.getParent());
		} 

		columns[0].setText( table1Name==null?"":table1Name );
		columns[1].setText( table2Name==null?"":joinTableName );
		
		//Update join column TableViewer 1
		tableDataModel1.clear();
		joinColumnsTable1.refresh();
		
		String msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, table1Name, joinTableName); 
		joinColumnsDescLabel1.setText(msg);
		joinColumnsDescLabel1.setToolTipText( msg );
		String[] referrerColumnValues = getTableColumns(table1Name);
		String[] referencedColumnValues = getTableColumns(joinTableName);
		
		updateCellEditors(joinColumnsTable1, referrerColumnValues, referencedColumnValues );

		//Update join column TableViewer 2
		columns = joinColumnsTable2.getTable().getColumns();
		columns[0].setText( joinTableName==null?"":joinTableName );
		columns[1].setText( table2Name==null?"":table2Name );
		tablesGroup1.layout();

		tableDataModel2.clear();
		joinColumnsTable2.refresh();
		msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, joinTableName, table2Name); 
		joinColumnsDescLabel2.setText(msg);
		joinColumnsDescLabel2.setToolTipText( msg );
		referrerColumnValues = getTableColumns(joinTableName);
		referencedColumnValues = getTableColumns(table2Name);
		updateCellEditors(joinColumnsTable2, referrerColumnValues, referencedColumnValues );
		
		tablesGroup2.layout();

		//Show the Join column TableViewer 2
		tablesGroup2.setVisible(true);
		
		
		((Composite)this.getControl()).layout(new Control[]{this.tablesGroup1, this.tablesGroup2});		
	}
	
	
	private void createAddRemoveButtonComposite(Composite tablesGroup, final TableViewer joinColumnsTable,  final ArrayList<SimpleJoin> tableDataModel) {
		//Add and Remove JoinColumns buttons
		Composite buttonComposite = new Composite(tablesGroup, SWT.NULL);
		GridLayout buttonLayout = new GridLayout(1, false);
		buttonComposite.setLayout(buttonLayout);
		GridData data =  new GridData();
		data.horizontalAlignment = GridData.FILL;
		data.verticalAlignment = GridData.BEGINNING;
		buttonComposite.setLayoutData(data);
		
		Button addButton = new Button(buttonComposite, SWT.PUSH);
		addButton.setText( JptUiEntityGenMessages.add );
		GridData gridData =  new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		addButton.setLayoutData(gridData);
		addButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {}
		
			@SuppressWarnings("unchecked")
			public void widgetSelected(SelectionEvent e) {
				
				SimpleJoin join = getDefaultNewJoin(joinColumnsTable);
				tableDataModel.add(join);
				joinColumnsTable.refresh();
				
				//Update Wizard model
				TreeMap<String, String> joins = null;
				if( joinColumnsTable == joinColumnsTable1 ){
					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
				}else{
					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
				}
				joins.put( join.foreignKey, join.primaryKey);
				
				updatePageComplete();
			}
		});
		
		Button removeButton = new Button(buttonComposite, SWT.PUSH);
		removeButton.setText( JptUiEntityGenMessages.remove );
		gridData =  new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		removeButton.setLayoutData(gridData);
		removeButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {}
		
			@SuppressWarnings("unchecked")
			public void widgetSelected(SelectionEvent e) {
				StructuredSelection selection = (StructuredSelection)joinColumnsTable.getSelection();
				if( selection.isEmpty())
					return;
				SimpleJoin join = (SimpleJoin)selection.getFirstElement();

				//Update TableViewer model
				tableDataModel.remove( join );
				//Update Wizard model
				
				TreeMap<String, String> joins = null;
				if( joinColumnsTable == joinColumnsTable1 ){
					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
				}else{
					joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
				}
				joins.remove(join.foreignKey);

				joinColumnsTable.refresh();
			}
		});
		
		addButton.setFocus();
		
	}

	protected SimpleJoin getDefaultNewJoin(TableViewer joinColumnsTable) {
		String table1Name = "";
		String table2Name = "";

		TreeMap<String, String> existingJoins = null;
		if( joinColumnsTable == this.joinColumnsTable1 ){
			existingJoins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
			if( this.getJoinTableName() == null) {
				table1Name = this.getReferrerTableName();
				table2Name = this.getReferencedTableName() ;
			}else{
				table1Name = this.getReferrerTableName();
				table2Name = this.getJoinTableName()  ;
			}
		}else{
			existingJoins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
			table1Name = this.getJoinTableName();
			table2Name = this.getReferencedTableName() ;
		}
		//find next available column
		String[] table1ColumnValues = getTableColumns(table1Name);
		String nextCol1 = "";
		for( String s: table1ColumnValues ){
			if( !existingJoins.keySet().contains(s)){
				nextCol1 = s;
				break;
			}
		}
		
		String[] table2ColumnValues = getTableColumns(table2Name);
		String nextCol2 = "";
		for( String s: table2ColumnValues ){
			if( !existingJoins.values().contains(s)){
				nextCol2 = s;
				break;
			}
		}
		return new SimpleJoin( nextCol1, nextCol2);
	}

	@Override
	public boolean canFlipToNextPage() {
		return isPageComplete();
	}
	
	public void updatePageComplete() {
		boolean ret = tableDataModel1.size()> 0 ;
		setPageComplete( ret );
	}	
	
	private Label createLabel(Composite container, int span, String text) {
		Label label = new Label(container, SWT.NONE);
		label.setText(text);
		GridData gd = new GridData();
		gd.horizontalSpan = span;
		label.setLayoutData(gd);
		return label;
	}

	private void createJoinColumnsTableControl1(Composite tablesGroup) {
		joinColumnsDescLabel1 = createLabel(tablesGroup, 2, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label );
		joinColumnsTable1 = createJoinColumnsTableControl(tablesGroup, this.tableDataModel1);
		createAddRemoveButtonComposite(tablesGroup, joinColumnsTable1, tableDataModel1);
	}
	
	private void createJoinColumnsTableControl2(Composite tablesGroup) {
		joinColumnsDescLabel2 = createLabel(tablesGroup, 2, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label );
		joinColumnsTable2 = createJoinColumnsTableControl(tablesGroup, this.tableDataModel2);
		createAddRemoveButtonComposite(tablesGroup, joinColumnsTable2, tableDataModel2);
	}
	
	private TableViewer createJoinColumnsTableControl(Composite parent, ArrayList<SimpleJoin> tableDataModel ){	
	
		TableLayoutComposite layout= new TableLayoutComposite(parent, SWT.NONE);
		addColumnLayoutData(layout);
		
		final org.eclipse.swt.widgets.Table table = new org.eclipse.swt.widgets.Table(layout, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER );
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		
		TableColumn referrerColumn = new TableColumn(table, SWT.NONE, JOINCOLUMN1_COLUMN_INDEX);
		referrerColumn.setText("%table1");
		referrerColumn.setResizable(true);

		TableColumn referencedColumn = new TableColumn(table, SWT.NONE, JOINCOLUMN2_COLUMN_INDEX);
		referencedColumn.setText("%table2");
		referencedColumn.setResizable(true);
		
		GridData gd= new GridData(GridData.FILL_BOTH);
		gd.heightHint= SWTUtil.getTableHeightHint(table, 3);
		gd.widthHint = 300;
		layout.setLayoutData(gd);

		TableViewer newJoinColumnsTable = new TableViewer(table);
		newJoinColumnsTable.setUseHashlookup(true);
		newJoinColumnsTable.setLabelProvider(this.buildTableTableLabelProvider());
		newJoinColumnsTable.setContentProvider(this.buildTableTableContentProvider());
		newJoinColumnsTable.setSorter(new ViewerSorter() {
			@Override
			public int compare(Viewer viewer, Object e1, Object e2) {
				return ((SimpleJoin) e1).foreignKey.compareTo(((SimpleJoin) e2).foreignKey);
			}
		});
		
		newJoinColumnsTable.addPostSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				//handleTablesListSelectionChanged(event);
			}
		});
		populateTableDataModel();
		newJoinColumnsTable.setInput( tableDataModel );
		return newJoinColumnsTable;
	}

	@SuppressWarnings("unchecked")
	public void populateTableDataModel(){
		HashMap<String, Object> dataModel = getWizardDataModel();
		TreeMap<String, String> joinColumns = (TreeMap<String, String>)dataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1);
		if( joinColumns!= null ){
			for( String referrerColumn : joinColumns.keySet() ){
				tableDataModel1.add(new SimpleJoin(referrerColumn, joinColumns.get(referrerColumn) ));
			}
		}
		
		TreeMap<String, String> joinColumns2 = (TreeMap<String, String>)dataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2);
		if( joinColumns2!= null ){
			for( String referrerColumn : joinColumns2.keySet() ){
				tableDataModel2.add(new SimpleJoin(referrerColumn, joinColumns2.get(referrerColumn) ));
			}
		}
		
	}
	
	private IContentProvider buildTableTableContentProvider() {
		return new JoinColumnsContentProvider();
	}

	
	private IBaseLabelProvider buildTableTableLabelProvider() {
		return new JoinColumnsTableLabelProvider();
	}
	
	
	private void addColumnLayoutData(TableLayoutComposite layout) {
		layout.addColumnData(new ColumnWeightData(50, true));
		layout.addColumnData(new ColumnWeightData(50, true));
	}
	
	
	private void updateCellEditors(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues ){
		joinColumnsTable.setColumnProperties(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES);
		ComboBoxCellEditor[] editors = new ComboBoxCellEditor[JOINCOLUMNS_TABLE_COLUMN_PROPERTIES.length];

		editors[JOINCOLUMN1_COLUMN_INDEX]= new ComboBoxCellEditor(joinColumnsTable.getTable(), referrerColumnValues, SWT.SINGLE);
		editors[JOINCOLUMN2_COLUMN_INDEX]= new ComboBoxCellEditor(joinColumnsTable.getTable(), referencedColumnValues, SWT.SINGLE);
		
		joinColumnsTable.setCellEditors(editors);
		joinColumnsTable.setCellModifier(this.buildTableTableCellModifier(joinColumnsTable, referrerColumnValues, referencedColumnValues ));
	}

	public String[] getTableColumns(String tableName){
		Schema schema = (Schema)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_SCHEMA);
		Table table = schema.getTableNamed(tableName);
		List<String> list = new ArrayList<String>();
		for (Column column : table.getColumns()) {
			list.add(column.getName());
		}
		String[] ret = new String[list.size()];
		list.toArray(ret);
		return ret;
	}
	
	private ICellModifier buildTableTableCellModifier(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues) {
		return new JoinColumnsCellModifier(joinColumnsTable, referrerColumnValues, referencedColumnValues);
	}	
	
	/**
	 * A ContentProvider translates the SimpleJoin list into a Collection for display 
	 *
	 */
	private class JoinColumnsContentProvider implements IStructuredContentProvider {

		JoinColumnsContentProvider() {
			super();
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}	
		public void dispose() {}
		public Object[] getElements(Object inputElement) {
			return ((Collection<?>) inputElement).toArray();
		}
	}
	
	/**
	 * Simple value object used as model backing the JFace table 
	 *
	 */
	private class SimpleJoin {
		public SimpleJoin(String foreignKey, String primaryKey) {
			this.foreignKey = foreignKey;
			this.primaryKey = primaryKey; 
		}
		public String foreignKey;
		public String primaryKey;
		
		@Override
		public String toString(){
			return "["+ this.foreignKey + " = " + this.primaryKey + "]";
		}
	}
	
	/**
	 *	A CellModifier to update the join columns in the wizard data model
	 */
	private class JoinColumnsCellModifier implements ICellModifier {
		private TableViewer joinColumnsTable;
		private String[] referrerColumnValues;
		private String[] referencedColumnValues;
		JoinColumnsCellModifier(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues) {
			super();
			this.joinColumnsTable = joinColumnsTable;
			this.referrerColumnValues = referrerColumnValues;
			this.referencedColumnValues = referencedColumnValues;
		}

		public boolean canModify(Object element, String property) {
			return true;
		}

		@SuppressWarnings("unchecked")
		public Object getValue(Object element, String property) {
//			SimpleJoin join = (SimpleJoin) element;
//			if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN2_COLUMN_INDEX])) {
//				return join.primaryKey;
//			}
//			return join.foreignKey;
			// returnt the index of the value in the ComboxCellEditor
			ArrayList<SimpleJoin> tableDataModel = (ArrayList<SimpleJoin>) joinColumnsTable.getInput();
			for(int i=0; i< tableDataModel.size(); i ++ ){
				if( tableDataModel.get(i) == element )
					return new Integer(i);
			}
			return new Integer(0);
			
		}

		/** 
		 * element is the selected TableItem
		 * value is the selected item index in the comboCellEditor 
		 */
		@SuppressWarnings("unchecked")
		public void modify(Object element, String property, Object value) {
			if ( ! (element instanceof TableItem)) {
				return;
			}
			Integer index = (Integer)value;
			TableItem item = (TableItem)element;
			boolean unchanged = false;
			SimpleJoin join = (SimpleJoin) item.getData();
			if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN1_COLUMN_INDEX])) {
				unchanged = join.foreignKey.equals( referrerColumnValues[ index.intValue() ] );
				if (! unchanged) {
					
					//update the wizard datamodel
					TreeMap<String, String> joins = null;
					if( joinColumnsTable == joinColumnsTable1 ){
						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
					}else{
						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
					}
					joins.remove(join.foreignKey);
					joins.put(referrerColumnValues[ index.intValue() ], join.primaryKey);

					//Update the TableViewer model
					join.foreignKey = referrerColumnValues[ index.intValue()];
					joinColumnsTable.refresh();
				}
				return;
			}
			
			if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN2_COLUMN_INDEX])) {
				unchanged = join.primaryKey.equals( referencedColumnValues[ index.intValue()] ) ;
				if (! unchanged) {
					//Update the TableViewer model
					join.primaryKey = referencedColumnValues[ index.intValue()] ;
					
					//Update wizard data model
					TreeMap<String, String> joins = null;
					if( joinColumnsTable == joinColumnsTable1 ){
						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 );
					}else{
						joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 );
					}
					joins.put(join.foreignKey, join.primaryKey);

					joinColumnsTable.refresh();
				}
			}
			
			
		}

	}

	/**
	 * A table label provider to return the join column names for display
	 *
	 */
	private final class JoinColumnsTableLabelProvider extends LabelProvider implements ITableLabelProvider {
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}
		public String getColumnText(Object element, int columnIndex) {
			if( !(element instanceof SimpleJoin) )
				return null;
			switch (columnIndex) {
	            case 0:
	            	return ((SimpleJoin)element).foreignKey;
	            case 1:
	            	return ((SimpleJoin)element).primaryKey;
	            default:
	            	Assert.isTrue(false);
	            	return null;
            }
		}
		@Override
		public String getText(Object element) {
		    return getColumnText(element, 0); // needed to make the sorter work
		}
	}
	
}
