/*
* 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.ui.table;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.IPropertySourceProvider;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.common.table.TableViewerSorter;
import org.teiid.designer.ui.properties.ModelObjectPropertyDescriptor;
import org.teiid.designer.ui.properties.extension.ModelExtensionPropertyDescriptor;
import org.teiid.designer.ui.properties.udp.ExtensionPropertyDescriptor;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
* ModelObjectTableModel
*
* @since 8.0
*/
public class ModelObjectTableModel implements UiConstants, EObjectPropertiesOrderPreferencesListener, DisposeListener {
private ArrayList instanceList;
private ArrayList rowList;
private HashMap rowMap = new HashMap();
private ArrayList propertyList;
private HashMap propertyIdMap;
private Map propIdDescriptorMap; // key=property ID, value=IPropertyDescriptor
private Map extensionDefnValueMap = new HashMap();
private IPropertySourceProvider propertySourceProvider;
private IPropertyDescriptor[] properties = new IPropertyDescriptor[0];
private TableViewer tableViewer;
private boolean columnsBuilt = false;
private boolean supportsDescription = true;
private String eObject;
private ArrayList tableColumns;
/**
* Obtains localized display text for the specified property.
* @param theProperty the property whose text is being requested
* @return the localized property text
*/
public static String getPropertyLabel(String theProperty) {
if (theProperty.equals(DESCRIPTION_KEY)) {
return DESCRIPTION_KEY;
} else if (theProperty.equals(LOCATION_KEY)) {
return LOCATION_KEY;
} else {
return theProperty;
}
}
public ModelObjectTableModel(String eObject, ArrayList instanceList, boolean supportsDescription) {
UiPlugin.getDefault().getEObjectPropertiesOrderPreferences().addEObjectPropertiesOrderPreferencesListener(this);
this.eObject = eObject;
this.instanceList = instanceList;
this.supportsDescription = supportsDescription;
refreshProperties();
buildPropertyIdMap();
}
public boolean canView() {
// DON'T call buildColumns();
return properties.length > 0;
}
public Object getPropertyId( String property ) {
if (this.extensionDefnValueMap.containsKey(property)) {
return this.extensionDefnValueMap.get(property);
}
return property;
}
public Object getPropertyIdAtIndex(int index) {
// DON'T call buildColumns();
return propertyIdMap.get(propertyList.get(index));
}
private void buildRowList() {
// DON'T call buildColumns();
rowList = new ArrayList(instanceList.size());
for ( int i=0 ; i<instanceList.size() ; ++i ) {
ModelRowElement row = new ModelRowElement((EObject) instanceList.get(i), this);
rowList.add(row);
rowMap.put(instanceList.get(i), row);
}
}
private void buildPropertyIdMap() {
// DON'T call buildColumns();
propertyList = new ArrayList(properties.length); // add space for location & description
propertyIdMap = new HashMap();
propIdDescriptorMap = new HashMap();
propertyIdMap.put(LOCATION_KEY, LOCATION_KEY);
propertyList.add(LOCATION_KEY);
for ( int size=properties.length, i=0 ; i<size ; ++i ) {
propertyIdMap.put(properties[i].getDisplayName(), properties[i].getId());
propertyList.add(properties[i].getDisplayName());
propIdDescriptorMap.put(properties[i].getId(), properties[i]);
}
if (supportsDescription) {
propertyIdMap.put(DESCRIPTION_KEY, DESCRIPTION_KEY);
propertyList.add(DESCRIPTION_KEY);
}
//Sort Property List Based on Preferences
ArrayList sortedColumns = UiPlugin.getDefault().getEObjectPropertiesOrderPreferences().getOrderedPropertyList(this.eObject);
ArrayList newList = new ArrayList();
ArrayList hiddenList = new ArrayList();
for (int i = 0; i < sortedColumns.size(); i++) {
PropertyOrder columnOrder = (PropertyOrder) sortedColumns.get(i);
if (propertyList.contains(columnOrder.getName())) {
if (columnOrder.isVisible()) {
newList.add(columnOrder.getName());
} else {
hiddenList.add(columnOrder.getName());
}
}
}
for (int i = 0; i < propertyList.size(); i++) {
if (!newList.contains(propertyList.get(i)) && !hiddenList.contains(propertyList.get(i))) {
newList.add(propertyList.get(i));
}
}
//Always Create One Column, Should Never Happen
if (newList.size() == 0) {
newList.add(propertyList.get(0));
}
propertyList = newList;
}
public void refreshProperties() {
if (instanceList.size() > 0) {
IPropertySource propertySource = getPropertySource((EObject)instanceList.get(0));
properties = propertySource.getPropertyDescriptors();
for (int i = 0; i < properties.length; ++i) {
if (properties[i] instanceof ModelObjectPropertyDescriptor) {
((ModelObjectPropertyDescriptor)properties[i]).setShowReadOnlyDialog(false);
((ModelObjectPropertyDescriptor)properties[i]).setLazyLoadValues(false);
} else if (properties[i] instanceof ExtensionPropertyDescriptor) {
((ExtensionPropertyDescriptor)properties[i]).setShowReadOnlyDialog(false);
}
}
}
}
public boolean isLocationColumn(Object object) {
return LOCATION_KEY.equals(object);
}
public boolean isDescriptionColumn(Object object) {
return DESCRIPTION_KEY.equals(object);
}
/**
* Gets the <code>IPropertyDescriptor</code> for the given property identifier.
* @param thePropertyId the identifier of the descriptor being requested
* @return the descriptor or <code>null</code> if not found
*/
public IPropertyDescriptor getPropertyDescriptor(Object thePropertyId) {
return (IPropertyDescriptor)propIdDescriptorMap.get(thePropertyId);
}
public void setTableViewer(TableViewer tableViewer) {
// DON'T call buildColumns();
if ( tableViewer == null || tableViewer.getTable().isDisposed() ) {
return;
}
this.tableViewer = tableViewer;
((Table) this.tableViewer.getControl()).addDisposeListener(this);
}
/**
* Builds the table columns. This should be done lazily only when the table is first shown.
* Calling this method more than once nothing.
*
*/
public void buildColumns() {
if (!columnsBuilt && (tableViewer != null)) {
//swjTODO: instrument the buildColumns method and find out why it is being called so often
// and where the large model performance bottlenecks are
//
// final IRunnableWithProgress op = new IRunnableWithProgress() {
// public void run(final IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
// monitor.beginTask("Building Table Columns...", 100); //Util.getString("ModelObjectTableModel.buildColumns"), 100); //$NON-NLS-1$
buildColumns(tableViewer.getTable());
// }
// };
//
// try {
// final ProgressMonitorDialog dlg = new ProgressMonitorDialog(tableViewer.getControl().getShell());
// dlg.run(false, false, op);
// } catch (final InterruptedException ignored) {
// } catch (final Exception err) {
// }
// need to hook up sorter now that columns are built
TableViewerSorter sorter = (TableViewerSorter)tableViewer.getSorter();
if (sorter != null) {
sorter.setSortListener();
}
}
}
private void buildColumns(Table table) {
if (!columnsBuilt) {
columnsBuilt = true;
if (this.tableColumns != null && this.tableColumns.size() > 0) {
for (int i = this.tableColumns.size() - 1; i > -1; i--) {
TableColumn column = (TableColumn) this.tableColumns.get(i);
column.dispose();
}
}
this.tableColumns = new ArrayList();
if ( propertyList.size() > 0 ) {
buildRowList();
String[] columnProperties = new String[propertyList.size()];
this.extensionDefnValueMap.clear();
for ( int i=0 ; i< propertyList.size(); ++i ) {
TableColumn column = new TableColumn(table, SWT.NONE);
this.tableColumns.add(column);
String columnHeader = (String)propertyList.get(i);
Object pId = getPropertyIdAtIndex(i);
if (pId instanceof ModelExtensionPropertyDescriptor) {
ModelExtensionPropertyDescriptor pDescriptor = (ModelExtensionPropertyDescriptor)pId;
pId = pDescriptor.getPropDefnId();
this.extensionDefnValueMap.put(pId, pDescriptor);
}
columnProperties[i] = (String)pId;
column.setText(columnHeader);
//swjTODO: set column data on this instead of hardcoding 80 pixels
column.setWidth(80);
}
tableViewer.setColumnProperties(columnProperties);
rebuildColumnEditors(table);
}
boolean startedTxn = ModelerCore.startTxn(false, false, null, null);
boolean succeeded = false;
try {
tableViewer.setInput(this);
succeeded = true;
} finally {
if ( startedTxn ) {
if (succeeded)
ModelerCore.commitTxn();
else
ModelerCore.rollbackTxn();
}
}
}
}
public CellEditor getCellEditor(int theColumn) {
buildColumns();
return tableViewer.getCellEditors()[theColumn];
}
public Object[] getElements(){
buildColumns();
return rowList.toArray();
}
public IPropertySource getPropertySource(EObject modelObject) {
// buildColumns();
if ( propertySourceProvider == null ) {
propertySourceProvider = ModelUtilities.getPropertySourceProvider();
}
return propertySourceProvider.getPropertySource(modelObject);
}
public ModelRowElement getRowElementForInstance(EObject instance) {
buildColumns();
return (ModelRowElement) rowMap.get(instance);
}
public void addRows(Collection eObjects) {
buildColumns();
if ( tableViewer == null || tableViewer.getTable().isDisposed() ) {
return;
}
for ( Iterator iter = eObjects.iterator() ; iter.hasNext() ; ) {
EObject eObject = (EObject) iter.next();
instanceList.add(eObject);
ModelRowElement row = new ModelRowElement(eObject, this);
rowList.add(row);
rowMap.put(eObject, row);
tableViewer.add(row);
}
}
public void removeRows(Collection eObjects) {
buildColumns();
if ( tableViewer == null || tableViewer.getTable().isDisposed() ) {
return;
}
for ( Iterator iter = eObjects.iterator() ; iter.hasNext() ; ) {
EObject eObject = (EObject) iter.next();
instanceList.remove(eObject);
ModelRowElement row = (ModelRowElement) rowMap.get(eObject);
if (row != null) {
rowList.remove(row);
rowMap.remove(eObject);
tableViewer.remove(row);
} // endif
}
}
public void setValueAt(Object theNewValue,
int theRow,
int theColumn) {
buildColumns();
CellEditor editor = getCellEditor(theColumn);
// jh Defect 19246: added this nullcheck
if ( editor != null ) {
ICellEditorValidator validator = editor.getValidator();
if ((validator == null) || (validator.isValid(theNewValue) == null)) {
ModelRowElement rowElement = (ModelRowElement)rowList.get(theRow);
Object propID = getPropertyIdAtIndex(theColumn);
if(propID instanceof String) {
rowElement.setValue((String)propID, theNewValue);
} else if(propID instanceof ExtensionPropertyDescriptor) {
rowElement.setValue((ExtensionPropertyDescriptor)propID, theNewValue);
}
tableViewer.refresh(rowElement);
}
}
}
/* (non-Javadoc)
* @see org.teiid.designer.ui.table.ModelTableColumnPreferencesListener#columnsChanged()
*/
@Override
public void propertiesChanged(List eObjects) {
if (eObjects == null || eObjects.contains(this.eObject)) {
this.columnsBuilt = false;
buildPropertyIdMap();
buildColumns();
}
}
/** Rebuild the columns.
* This can be useful if something large has changed, such
* as the backing file's read-only state.
*/
public void rebuildColumnEditors(Table table) {
int size = propertyList.size();
if ( size > 0 ) {
CellEditor[] cellEditors = new CellEditor[size];
for ( int i=0 ; i< size; ++i ) {
if (isLocationColumn(propertyList.get(i))) {
cellEditors[i] = new TextCellEditor(table);
} else if (isDescriptionColumn(propertyList.get(i))) {
cellEditors[i] = new TextCellEditor(table);
} else {
cellEditors[i] = ((IPropertyDescriptor) propIdDescriptorMap.get(propertyIdMap.get(propertyList.get(i)))).createPropertyEditor(table);
}
}
tableViewer.setCellEditors(cellEditors);
}
}
@Override
public void widgetDisposed(DisposeEvent e) {
UiPlugin.getDefault().getEObjectPropertiesOrderPreferences().removeEObjectPropertiesOrderPreferencesListener(this);
}
}