blob: a90c0bf75282202e1391b9f25c8bbbb03d036e23 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 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.jpa.eclipselink.ui.internal.wizards;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Path;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
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.window.Window;
import org.eclipse.jpt.common.core.JptResourceType;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.MappingKeys;
import org.eclipse.jpt.jpa.core.resource.xml.JpaXmlResource;
import org.eclipse.jpt.jpa.eclipselink.ui.internal.EclipseLinkUiMessages;
import org.eclipse.jpt.jpa.eclipselink.ui.internal.dialogs.AddVirtualAttributeDialog;
import org.eclipse.jpt.jpa.eclipselink.ui.internal.entity.data.model.DynamicEntityField;
import org.eclipse.jpt.jpa.ui.details.MappingUiDefinition;
import org.eclipse.jpt.jpa.ui.internal.wizards.entity.data.model.IEntityDataModelProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.wst.common.componentcore.internal.operation.IArtifactEditOperationDataModelProperties;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
public class DynamicEntityFieldTableSection extends Composite {
private IDataModel model;
private Table mTableWidget = null;
private TableViewer mTableViewer = null;
private final int NAME_COLUMN = 0;
private final int MAPPING_TYPE_COLUMN = 1;
private final int ATTRIBUTE_TYPE_COLUMN = 2;
private Button addButton;
private Button editButton;
private Button removeButton;
private String propertyName;
/**
* @param parent the main composite - DynamicEntityFieldsWizardPage
* @param model the data model representation
* @param propertyName data property name
*/
public DynamicEntityFieldTableSection(Composite parent, IDataModel model, String propertyName) {
super(parent, SWT.NONE);
this.model = model;
this.propertyName = propertyName;
GridLayout layout = new GridLayout(2, false);
layout.marginHeight = 4;
layout.marginWidth = 0;
this.setLayout(layout);
this.setLayoutData(new GridData(GridData.FILL_BOTH));
// table widget
mTableWidget = new Table(this, SWT.FULL_SELECTION | SWT.BORDER);
mTableWidget.setHeaderVisible(true);
mTableWidget.setLinesVisible(true);
GridData data = new GridData(GridData.FILL_BOTH);
data.verticalSpan = 2;
mTableWidget.setLayoutData(data);
TableColumn nameColumn = new TableColumn(mTableWidget, SWT.NONE);
nameColumn.setText(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_nameColumnLabel);
TableColumn mappingTypeColumn = new TableColumn(mTableWidget, SWT.NONE);
mappingTypeColumn.setText(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_mappingTypeColumnLabel);
TableColumn attrTypeColumn = new TableColumn(mTableWidget, SWT.NONE);
attrTypeColumn.setText(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_attributeTypeColumnLabel);
mTableViewer = new TableViewer(mTableWidget);
mTableViewer.setContentProvider(new EntityRowContentProvider());
mTableViewer.setLabelProvider(new EntityRowLabelProvider());
mTableViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
handleEditButtonSelected();
updatePrimaryKeyFieldProperty();
}
});
// add, edit and remove buttons
final Composite buttonComposition = new Composite(this, SWT.NULL);
layout = new GridLayout();
layout.marginHeight = 0;
buttonComposition.setLayout(layout);
buttonComposition.setLayoutData(new GridData(GridData.FILL_VERTICAL | GridData.VERTICAL_ALIGN_BEGINNING));
addButton = new Button(buttonComposition, SWT.PUSH);
addButton.setText(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_addButtonLabel);
addButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL));
addButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
handleAddButtonSelected();
updatePrimaryKeyFieldProperty();
}
public void widgetDefaultSelected(SelectionEvent event) {
//Do nothing
}
});
editButton = new Button(buttonComposition, SWT.PUSH);
editButton.setText(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_editButtonLabel);
editButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL));
editButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
handleEditButtonSelected();
updatePrimaryKeyFieldProperty();
}
public void widgetDefaultSelected(SelectionEvent event) {
//Do nothing
}
});
editButton.setEnabled(false);
removeButton = new Button(buttonComposition, SWT.PUSH);
removeButton.setText(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_removeButtonLabel);
removeButton.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL));
removeButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
handleRemoveButtonSelected();
updatePrimaryKeyFieldProperty();
}
public void widgetDefaultSelected(SelectionEvent event) {
//Do nothing
}
});
removeButton.setEnabled(false);
mTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (editButton != null) {
boolean enabled = ((IStructuredSelection) selection).size() == 1;
editButton.setEnabled(enabled);
}
removeButton.setEnabled(!selection.isEmpty());
}
});
this.addControlListener(new ColumnControlListener(buttonComposition));
}
/**
* This method process the Add... button pressed event.
* It opens dialog to add a new dynamic entity field
*/
private void handleAddButtonSelected() {
AddFieldDialog dialog = new AddFieldDialog(getShell(), this.getJpaProject());
int result = dialog.open();
if (result == Window.CANCEL) {
return;
}
DynamicEntityField entityField = dialog.getEntityField();
addEntityField(entityField);
}
/**
* Add the given dynamic entity field to the table
*
* @param DynamicEntityField
* @return the DynamicEntityField which is to be added to the table
*/
private void addEntityField(DynamicEntityField field) {
if (field == null)
return;
List<DynamicEntityField> valueList = (ArrayList<DynamicEntityField>) mTableViewer.getInput();
if (valueList == null)
valueList = new ArrayList<DynamicEntityField>();
valueList.add(field);
setInput(valueList);
}
/**
* This method process the Edit... button pressed event.
* It opens dialog to edit a chosen dynamic entity field
*/
private void handleEditButtonSelected() {
ISelection s = mTableViewer.getSelection();
if (!(s instanceof IStructuredSelection))
return;
IStructuredSelection selection = (IStructuredSelection) s;
if (selection.size() != 1)
return;
Object selectedObj = selection.getFirstElement();
DynamicEntityField fieldForEdit = (DynamicEntityField) selectedObj;
int index = mTableWidget.getSelectionIndex();
EditFieldDialog dialog = new EditFieldDialog(getShell(), this.getJpaProject(), fieldForEdit);
dialog.open();
DynamicEntityField entityField = dialog.getEntityField();
if (entityField != null) {
editEntityField(index, entityField);
}
}
/**
* Edit a chosen dynamic entity field from the table
* @param index the index of the dynamic entity field in the table
* @param field the edited dynamic entity field
*/
private void editEntityField(int index, DynamicEntityField field) {
if (field == null)
return;
List<DynamicEntityField> valueList = (ArrayList<DynamicEntityField>) mTableViewer.getInput();
if (valueList == null) {
valueList = new ArrayList<DynamicEntityField>();
}
if (index == -1) {
valueList.add(field);
} else {
valueList.set(index, field);
}
setInput(valueList);
}
/**
* This method process the Remove button pressed event.
*/
private void handleRemoveButtonSelected() {
ISelection selection = mTableViewer.getSelection();
if (selection.isEmpty() || !(selection instanceof IStructuredSelection))
return;
List<DynamicEntityField> selectedObject = ((IStructuredSelection) selection).toList();
removeEntityField(selectedObject);
}
/**
* Removes the selected dynamic entity field(s) from the table
* @param fields list of dynamic entity fields which should be removed
*/
private void removeEntityField(Collection<DynamicEntityField> fields) {
List<DynamicEntityField> valueList = (ArrayList<DynamicEntityField>) mTableViewer.getInput();
valueList.removeAll(fields);
setInput(valueList);
}
/**
* Set the input of the table
* @param input the list of dynamic entity fields which have to be presented in the table
*/
private void setInput(List<DynamicEntityField> input) {
mTableViewer.setInput(input);
// Create a new list to trigger property change
ArrayList<DynamicEntityField> newInput = new ArrayList<DynamicEntityField>();
newInput.addAll(input);
model.setProperty(propertyName, newInput);
}
/**
* @return the TableViewer of the table
*/
public TableViewer getTableViewer() {
return mTableViewer;
}
/**
* Update PK fields property when any field(s) added to, edited in, or removed from the field table viewer
*/
private void updatePrimaryKeyFieldProperty() {
List<DynamicEntityField> pkFields = new ArrayList<DynamicEntityField>();
TableItem[] children = mTableViewer.getTable().getItems();
for (int i = 0; i < children.length; i++) {
TableItem item = children[i];
DynamicEntityField field = (DynamicEntityField)item.getData();
if (field.getMappingType().getKey().equals(MappingKeys.ID_ATTRIBUTE_MAPPING_KEY)) {
field.setKey(true);
pkFields.add(field);
}
}
DynamicEntityFieldTableSection.this.model.setProperty(IEntityDataModelProperties.PK_FIELDS, pkFields);
}
// ********** Control listener for field columns **************
private final class ColumnControlListener extends ControlAdapter {
private final Composite buttonComposition;
private ColumnControlListener(Composite buttonComposition) {
this.buttonComposition = buttonComposition;
}
@Override
public void controlResized(ControlEvent e) {
Table table = mTableViewer.getTable();
Rectangle area = table.getParent().getClientArea();
Point preferredSize = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
TableColumn[] columns = table.getColumns();
Point buttonArea = buttonComposition.computeSize(SWT.DEFAULT, SWT.DEFAULT);
int width = area.width - 3 * table.getBorderWidth();
if (preferredSize.y > area.height + table.getHeaderHeight()) {
// Subtract the scrollbar width from the total column width
// if a vertical scrollbar will be required
Point vBarSize = table.getVerticalBar().getSize();
width -= vBarSize.x;
}
Point oldSize = table.getSize();
int consumeWidth = 0;
for (int i = 0; i < columns.length; i++) {
if (oldSize.x > area.width) {
// table is getting smaller so make the columns
// smaller first and then resize the table to
// match the client area width
consumeWidth = setColumntWidth(width, columns, consumeWidth, i);
table.setSize(area.width - buttonArea.x, area.height);
} else {
// table is getting bigger so make the table
// bigger first and then make the columns wider
// to match the client area width
consumeWidth = setColumntWidth(width, columns, consumeWidth, i);
table.setSize(area.width - buttonArea.x, area.height);
}
}
}
private int setColumntWidth(int width, TableColumn[] columns, int consumeWidth, int i) {
columns[i].setWidth(width / (columns.length + 1));
consumeWidth += columns[i].getWidth();
return consumeWidth;
}
}
// ********** Providers for the dynamic entity field table viewer **************
/**
* The content provider for the table items
*/
protected class EntityRowContentProvider implements IStructuredContentProvider {
public boolean isDeleted(Object element) {
return false;
}
public Object[] getElements(Object element) {
if (element instanceof List) {
return ((List) element).toArray();
}
return new Object[0];
}
public void inputChanged(Viewer aViewer, Object oldInput, Object newInput) {
//Default nothing
}
public void dispose() {
//Default nothing
}
}
/**
* The label provider for the table items
*/
protected class EntityRowLabelProvider extends LabelProvider implements ITableLabelProvider {
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
DynamicEntityField entity = (DynamicEntityField) element;
if (columnIndex == NAME_COLUMN) {
return entity.getName();
}
if (columnIndex == MAPPING_TYPE_COLUMN) {
return entity.getMappingType().getLabel();
}
if (columnIndex == ATTRIBUTE_TYPE_COLUMN) {
return entity.getFqnTypeName();
}
return "";
}
@Override
public Image getImage(Object element) {
return null;
}
@Override
public String getText(Object element) {
String[] array = (String[]) element;
if (array.length > 0) {
return array[0];
} else {
return super.getText(element);
}
}
}
// ********* Add dynamic entity field dialog ******************
/**
* The dialog which collect the information (name, mapping type, and attribute type) for a new dynamic entity field
*/
private class AddFieldDialog extends AddVirtualAttributeDialog {
protected DynamicEntityField entityField;
protected final JpaProject jpaProject;
/**
* Constructs AddFieldDialog
* @param shell
* @param jpaProject the selected jpaProject
*/
public AddFieldDialog(Shell shell, JpaProject jpaProject) {
super(shell, null);
this.jpaProject = jpaProject;
setTitle(EclipseLinkUiMessages.DynamicEntityFieldsWizardPage_addDynamicEntityFieldDialog_title);
}
/* Create the area of dialog
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
public Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
return composite;
}
/* Processes OK button pressed event.
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
*/
@Override
protected void okPressed() {
/**
* @see org.eclipse.jpt.jpa.eclipselink.ui.internal.entity.data.model.DynamicEntityField
*/
DynamicEntityField field = new DynamicEntityField();
field.setMappingType(this.getMappingUiDefinition(this.mappingCombo));
field.setFqnTypeName(this.attributeTypeText.getText());
field.setName(this.nameText.getText());
entityField = field;
setReturnCode(OK);
close();
}
private MappingUiDefinition<?,?> getMappingUiDefinition(ComboViewer mappingType) {
StructuredSelection selection = (StructuredSelection) mappingType.getSelection();
return (selection.isEmpty()) ? null : (MappingUiDefinition<?,?>) selection.getFirstElement();
}
/**
* @return the dynamic entity field representation with the information collected from the dialog
*/
public DynamicEntityField getEntityField() {
return this.entityField;
}
// ********** override super class methods ************
@Override
protected JpaProject getJpaProject() {
return this.jpaProject;
}
@Override
protected JptResourceType getJptResourceType() {
String xmlName = model.getStringProperty(IEntityDataModelProperties.XML_NAME);
return this.getOrmXmlResource(xmlName).getResourceType();
}
protected JpaXmlResource getOrmXmlResource(String xmlName) {
return this.jpaProject == null ? null : this.jpaProject.getMappingFileXmlResource(new Path(xmlName));
}
}
// ********* Edit dynamic entity field dialog ******************
private class EditFieldDialog extends AddFieldDialog {
public EditFieldDialog(Shell shell, JpaProject jpaProject, DynamicEntityField field) {
super(shell, jpaProject);
this.entityField = field;
}
/* Create the area of the dialog
*/
@Override
public Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
this.nameText.setText(this.entityField.getName());
this.mappingCombo.setSelection(new StructuredSelection(this.entityField.getMappingType()));
this.attributeTypeText.setText(this.entityField.getFqnTypeName());
return composite;
}
}
//************* misc **************
protected JpaProject getJpaProject() {
return (JpaProject) getIProject().getAdapter(JpaProject.class);
}
protected IProject getIProject() {
String projectName = model.getStringProperty(IArtifactEditOperationDataModelProperties.PROJECT_NAME);
return ProjectUtilities.getProject(projectName);
}
}