/*
* 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.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.IItemPropertySource;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.ObjectExtension;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.properties.ModelObjectPropertySource;
import org.teiid.designer.ui.properties.extension.ModelExtensionPropertyDescriptor;
import org.teiid.designer.ui.properties.udp.ExtensionPropertyDescriptor;
import org.teiid.designer.ui.properties.udp.ExtensionPropertySource;
import org.teiid.designer.ui.viewsupport.ModelObjectUtilities;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
/**
* ModelRowElement represents a row of properties in the ModelTableEditor's TableViewer.
*
* @since 8.0
*/
public class ModelRowElement {
private EObject modelObject;
private ModelObjectTableModel tableModel;
/** the PropertySource for this EObject, obtained from the EMF PropertySourceProvider */
private IPropertySource propertySource;
private Map propIdDescriptorMap; // key=property ID, value=IPropertyDescriptor
/**
* Construct an instance of ModelRowElement representing the specified modelObject.
* @param modelObject the model object
* @param tableModel the table model
*/
public ModelRowElement(EObject modelObject, ModelObjectTableModel tableModel) {
this.modelObject = modelObject;
this.tableModel = tableModel;
this.propertySource = tableModel.getPropertySource(modelObject);
setModelExtensionPropertyIdDescriptorMap();
}
/**
* Populates a map with the ModelExtensionProperyDescriptors for setting values on the extension properties. The ModelObjectTableModel handles
* other properties, but it's method does not work with the Extension Properties. They need the unique ModelExtensionPropertyDescriptor to set
* the extension properties
*/
private void setModelExtensionPropertyIdDescriptorMap() {
propIdDescriptorMap = new HashMap();
IPropertyDescriptor[] properties = this.propertySource.getPropertyDescriptors();
for (int i = 0; i < properties.length; ++i) {
Object id = properties[i].getId();
if(id instanceof ModelExtensionPropertyDescriptor) {
propIdDescriptorMap.put(((ModelExtensionPropertyDescriptor) id).getPropDefnId(), properties[i]);
}
}
}
/**
* Gets the <code>IPropertyDescriptor</code> for the given property identifier.
* @param thePropertyDefnId the identifier of the descriptor being requested
* @return the descriptor or <code>null</code> if not found
*/
private IPropertyDescriptor getModelExtensionPropertyDescriptor(String thePropertyDefnId) {
return (IPropertyDescriptor)propIdDescriptorMap.get(thePropertyDefnId);
}
/**
* Get the true Object value for the modelObject property that can be used in a cell editor.
* @param propertyID the property id
* @return the value object
*/
public final Object getValueObject(String propertyID) {
if ( propertyID.equals(UiConstants.LOCATION_KEY) ) {
// return the name of this object's parent
return ModelUtilities.getEMFLabelProvider().getText(modelObject.eContainer());
} else if ( propertyID.equals(UiConstants.DESCRIPTION_KEY) ) {
// return this object's description
return ModelObjectUtilities.getDescription(modelObject);
} else {
// get the value from the PropertySource.
Object propId = getPropertyId(propertyID);
Object value = propertySource.getPropertyValue(propId);
if ( value instanceof ItemPropertyDescriptor.PropertyValueWrapper ) {
value = ((ItemPropertyDescriptor.PropertyValueWrapper) value).getEditableValue(this.modelObject);
}
return value;
}
}
/**
* Determine if the proposed value is invalid and, if so, return an error message that
* can be displayed to the user.
* @param propertyID the property id
* @param value the proposed value
* @return the invalid value message
*/
public final String getInvalidValueMessage(String propertyID, Object value) {
String result = null;
// need to convert String literals to EDataType values
Object object = propertySource.getEditableValue();
IItemPropertySource itemSource = (IItemPropertySource) ModelerCore.getMetamodelRegistry().getAdapterFactory().adapt(object, IItemPropertySource.class);
IItemPropertyDescriptor itemDescriptor = itemSource.getPropertyDescriptor(object, propertyID);
if (itemDescriptor != null) {
EStructuralFeature feature = (EStructuralFeature) itemDescriptor.getFeature(object);
if ( value instanceof String ) {
if ( ModelerCore.getModelEditor().isDatatypeFeature( modelObject, feature) ) {
try {
// Shorten datatype if it's the long version
String theValue = getDatatypeShortString((String)value);
EObject testValue = ModelerCore.getDatatypeManager(modelObject,true).findDatatype( theValue );
if ( testValue == null ) {
result = UiConstants.Util.getString("ModelRowElement.invalidValueError", value, propertyID); //$NON-NLS-1$
}
} catch ( ModelerCoreException mce ) {
ModelerCore.Util.log(IStatus.ERROR, mce, mce.getMessage());
}
} else {
if ( feature.getEType() instanceof EDataType ) {
final EDataType dt = (EDataType)feature.getEType();
final EPackage ePackage = dt.getEPackage();
final EFactory fac = ePackage.getEFactoryInstance();
// Try to convert to correct type from String
try {
fac.createFromString(dt, (String)value);
// Handle exception - error in conversion
} catch (Exception e) {
result = UiConstants.Util.getString("ModelRowElement.invalidValueError", value, propertyID); //$NON-NLS-1$
}
}
}
} else {
result = UiConstants.Util.getString("ModelRowElement.unsupportedError", propertyID); //$NON-NLS-1$
}
}
return result;
}
/**
* If a colon is detected in the long string, shorten it so that the value can be set properly.
* @param longString the full datatype string
* @return the shortened datatype string
*/
private String getDatatypeShortString(String longString) {
if(longString==null) return null;
String modValue = longString;
int colonIndex = longString.indexOf(':');
if(colonIndex!=-1) {
modValue = longString.substring(0,colonIndex).trim();
}
return modValue;
}
/**
* Determine if the proposed value is invalid and, if so, return an error message that
* can be displayed to the user.
* @param propertyID the property id
* @param value the property value
* @return the column error message
*/
public final String getReferenceColumnMessage(String propertyID, Object value) {
String result = null;
// need to convert String literals to EDataType values
Object object = propertySource.getEditableValue();
IItemPropertySource itemSource = (IItemPropertySource) ModelerCore.getMetamodelRegistry().getAdapterFactory().adapt(object, IItemPropertySource.class);
IItemPropertyDescriptor itemDescriptor = itemSource.getPropertyDescriptor(object, propertyID);
if (itemDescriptor != null) {
EStructuralFeature feature = (EStructuralFeature) itemDescriptor.getFeature(object);
if ( value instanceof String ) {
if ( !ModelerCore.getModelEditor().isDatatypeFeature( modelObject, feature) ) {
if ( !(feature.getEType() instanceof EDataType) ) {
// if not a DataType, it will be an EReference, protect it:
result = ClipboardPasteStatusRecord.REFERENCE_COLUMN_MSG;
}
}
}
}
return result;
}
/**
* Determine if the proposed value is invalid and, if so, return an error message that
* can be displayed to the user.
* @param propertyID the property descriptor
* @param value the value
* @return the invalid value message
*/
public final String getInvalidValueMessage(ExtensionPropertyDescriptor propertyID, Object value) {
String result = null;
EObject eObj = propertyID.getExtensionObject();
if(eObj!=null && eObj instanceof ObjectExtension) {
ObjectExtension objExt = (ObjectExtension)eObj;
ExtensionPropertySource eps = new ExtensionPropertySource(objExt.getExtendedObject());
// Determine if the supplied value can be converted to appropriate type
if(!eps.canConvertToCorrectDatatype(propertyID,value)) {
result = UiConstants.Util.getString("ModelRowElement.invalidValueError", value, propertyID.toString()); //$NON-NLS-1$
}
}
return result;
}
/**
* Get the value for the modelObject for the specified propertyID.
* @param propertyID the property id
* @param value the value
*/
public final void setValue(String propertyID, Object value){
if ( propertyID.equals(UiConstants.DESCRIPTION_KEY) ) {
String desc = ModelObjectUtilities.getDescription(modelObject);
if ( desc == null ) {
// don't set empty string
if ( value != null && ! PluginConstants.EMPTY_STRING.equals(value) ) {
ModelObjectUtilities.setDescription(modelObject, (String) value, this);
}
} else {
if ( ! desc.equals(value) ) {
ModelObjectUtilities.setDescription(modelObject, (String) value, this);
}
}
} else if ( propertyID.equals(UiConstants.LOCATION_KEY) ) {
// do nothing : can't set a location
} else {
try {
Object object = propertySource.getEditableValue();
IItemPropertySource itemSource = (IItemPropertySource) ModelerCore.getMetamodelRegistry().getAdapterFactory().adapt(object, IItemPropertySource.class);
IItemPropertyDescriptor itemDescriptor = itemSource.getPropertyDescriptor(object, propertyID);
if ( itemDescriptor != null ) {
EStructuralFeature feature = (EStructuralFeature) itemDescriptor.getFeature(object);
if ( value instanceof String ) {
if ( ModelerCore.getModelEditor().isDatatypeFeature( modelObject, feature) ) {
String theValue = getDatatypeShortString((String)value);
try {
value = ModelerCore.getDatatypeManager(modelObject,true).findDatatype( theValue );
} catch ( ModelerCoreException mce ) {
ModelerCore.Util.log(IStatus.ERROR, mce, mce.getMessage());
}
}
}
}
// Get the property Id.
Object propId = getPropertyId(propertyID);
// Get current Value from propertySource
Object currentValue = propertySource.getPropertyValue(propId);
if ( currentValue == null ) {
if ( value != null ) {
propertySource.setPropertyValue(propId, value);
}
} else {
if ( ! currentValue.equals(value) ) {
propertySource.setPropertyValue(propId, value);
}
}
} catch (Exception e) {
String message = UiConstants.Util.getString("ModelRowElement.setValueError", value, propertyID, modelObject.eClass().getName()); //$NON-NLS-1$
UiConstants.Util.log(IStatus.ERROR, e, message);
String title = UiConstants.Util.getString("ModelRowElement.setValueErrorTitle"); //$NON-NLS-1$
MessageDialog.openError(null, title, message);
}
}
}
/**
* Set the value for the modelObject for the specified propertyID.
* @param descriptor the property descriptor
* @param value the new property value
*/
public final void setValue(ExtensionPropertyDescriptor descriptor, Object value){
try {
if(propertySource instanceof ModelObjectPropertySource) {
((ModelObjectPropertySource)propertySource).setPropertyValue(descriptor,value);
}
} catch (Exception e) {
String message = UiConstants.Util.getString("ModelRowElement.setValueError", value, descriptor.toString(), modelObject.eClass().getName()); //$NON-NLS-1$
UiConstants.Util.log(IStatus.ERROR, e, message);
String title = UiConstants.Util.getString("ModelRowElement.setValueErrorTitle"); //$NON-NLS-1$
MessageDialog.openError(null, title, message);
}
}
/**
* Get string representation of the value for the modelObject for the indexed property.
* @param index the column index
* @return the value object
*/
public final Object getValue(int index){
if( modelObject.eIsProxy() ) {
return null;
}
Object result = null;
Object propertyId = tableModel.getPropertyIdAtIndex(index);
if (tableModel.isLocationColumn(propertyId)) {
EObject container = modelObject.eContainer();
if( container != null ) {
result = ModelUtilities.getEMFLabelProvider().getText(modelObject.eContainer());
} else {
try {
ModelResource mr = ModelUtilities.getModelResource(modelObject);
if( mr != null && mr.getCorrespondingResource() != null ) {
result = ModelUtilities.getModelName(modelObject);
}
} catch (ModelWorkspaceException ex) {
String message = "[ModelRowElement.getValue()]: exception finding resource for model"; //$NON-NLS-1$
UiConstants.Util.log(IStatus.ERROR, ex, message);
}
}
} else if (tableModel.isDescriptionColumn(propertyId)) {
result = ModelObjectUtilities.getDescription(modelObject);
} else {
IPropertyDescriptor descriptor = getPropertyDescriptor(propertyId);
if( descriptor != null ) {
// if the propertyId is a ModelExtensionProperty, get the propId from the descriptor
if(propertyId instanceof ModelExtensionPropertyDescriptor) {
propertyId = descriptor.getId();
}
result = descriptor.getLabelProvider().getText(propertySource.getPropertyValue(propertyId));
}
}
return result;
}
/**
* Convenience method for obtaining the PropertyDescriptor from the propertyId object
* @param propertyId the property id object
* @return the property descriptor
*/
public final IPropertyDescriptor getPropertyDescriptor(Object propertyId) {
IPropertyDescriptor descriptor = this.tableModel.getPropertyDescriptor(propertyId);
// if the propertyId is a ModelExtensionProperty, get the descriptor from this ModelRowElement
if(propertyId instanceof ModelExtensionPropertyDescriptor) {
descriptor = getModelExtensionPropertyDescriptor(((ModelExtensionPropertyDescriptor)propertyId).getPropDefnId());
}
return descriptor;
}
/**
* Convenience method for obtaining the PropertyId object from the propertyId string
* @param propertyId the property id string
* @return the property id
*/
public final Object getPropertyId(String propertyId) {
Object propId = tableModel.getPropertyId(propertyId);
if(propId instanceof ModelExtensionPropertyDescriptor) {
IPropertyDescriptor descriptor = getModelExtensionPropertyDescriptor(((ModelExtensionPropertyDescriptor)propId).getPropDefnId());
propId = descriptor.getId();
}
return propId;
}
/**
* Convenience method for obtaining a propertyID for a column index.
* @param index the column index
* @return the property id
*/
public final Object getPropertyIdForColumn(int index) {
return tableModel.getPropertyIdAtIndex(index);
}
/**
* Get the EObject represented by this row.
* @return the ModelObject for this row
*/
public EObject getModelObject() {
return modelObject;
}
}