/*
* 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.properties.sdt;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.ui.views.properties.ComboBoxLabelProvider;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.types.DatatypeConstants;
import org.teiid.designer.core.types.EnterpriseDatatypeInfo;
import org.teiid.designer.metamodels.xsd.aspects.sql.XsdSimpleTypeDefinitionAspect;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.properties.ModelObjectPropertySource;
import org.teiid.designer.ui.viewsupport.ModelObjectUtilities;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* SimpleDatatypePropertySource is a property source for adding runtime type properties to
* XSDSimpleTypeDefinitions. It works by wrapping a delegate PropertySource from EMF and
* adding the runtime type DOM Node properties. This class creates property descriptors for
* the DOM Node properties and handles the get/set of property values. All other EObject
* properties on XSDSimpleTypeDefinition are handled by the EMF property source.
*
* @since 8.0
*/
public class SimpleDatatypePropertySource implements IPropertySource {
private static final String TYPE_NAME = UiConstants.Util.getString("RuntimeTypePropertyDescriptor.runtimeTypeName"); //$NON-NLS-1$
private static final String TYPE_FIXED = UiConstants.Util.getString("RuntimeTypePropertyDescriptor.runtimeTypeFixed"); //$NON-NLS-1$
public static final String TYPE_NAME_DESCRIPTION = UiConstants.Util.getString("RuntimeTypePropertyDescriptor.runtimeTypeDescription"); //$NON-NLS-1$
public static final String TYPE_FIXED_DESCRIPTION = UiConstants.Util.getString("RuntimeTypePropertyDescriptor.runtimeTypeFixedDescription"); //$NON-NLS-1$
public static String[] runtimeTypeFixedArray = new String[2];
static {
runtimeTypeFixedArray[0] = Boolean.TRUE.toString();
runtimeTypeFixedArray[1] = Boolean.FALSE.toString();
}
public static String[] runtimeTypeArray = (String[]) DatatypeConstants.getRuntimeTypeNames().toArray(runtimeTypeFixedArray);
private XSDSimpleTypeDefinition datatype;
private IPropertySource delegate;
private List descriptorList;
private ILabelProvider runtimeTypeLabelProvider;
private ILabelProvider runtimeTypeFixedLabelProvider;
/**
* Construct an instance of SimpleDatatypePropertySource.
*/
public SimpleDatatypePropertySource(XSDSimpleTypeDefinition datatype, IPropertySource emfPropertySource) {
this.delegate = emfPropertySource;
this.descriptorList = new ArrayList();
this.runtimeTypeLabelProvider = new ComboBoxLabelProvider(runtimeTypeArray);
this.runtimeTypeFixedLabelProvider = new ComboBoxLabelProvider(runtimeTypeFixedArray);
this.datatype = datatype;
}
/*
* Update the list of property descriptors for the XSDSimpleTypeDefinition.
* @since 4.2
*/
private void updateDescriptorList() {
// build the descriptor list
EnterpriseDatatypeInfo edtInfo = ModelerCore.getDatatypeManager(datatype, true).getEnterpriseDatatypeInfo(datatype);
Element element = datatype.getElement();
Document doc = element.getOwnerDocument();
Node node = doc.createAttribute(XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME);
Object uuid = (edtInfo != null && edtInfo.getUuid() != null ) ? (Object) edtInfo.getUuid() : ModelerCore.getDatatypeManager(datatype).getUuid(datatype);
node.setNodeValue(uuid != null ? uuid.toString() : null);
descriptorList.add(new NodePropertyDescriptor(datatype, node));
// cannot edit any property of builtin types
boolean isEditable = !ModelerCore.getWorkspaceDatatypeManager().isBuiltInDatatype(datatype);
node = doc.createAttribute(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME);
node.setNodeValue(edtInfo.getRuntimeType());
ModelResourceComboBoxPropertyDescriptor descriptor = new ModelResourceComboBoxPropertyDescriptor(datatype, node, TYPE_NAME, runtimeTypeArray);
descriptor.setEditable(isEditable);
descriptor.setDescription(TYPE_NAME_DESCRIPTION);
descriptor.setLabelProvider(runtimeTypeLabelProvider);
descriptorList.add(descriptor);
node = doc.createAttribute(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME);
Boolean runtimeTypeFixed = edtInfo.getRuntimeTypeFixed();
node.setNodeValue(runtimeTypeFixed != null ? runtimeTypeFixed.toString() : null);
descriptor = new ModelResourceComboBoxPropertyDescriptor(datatype, node, TYPE_FIXED, runtimeTypeFixedArray);
descriptor.setEditable(isEditable);
descriptor.setDescription(TYPE_FIXED_DESCRIPTION);
descriptor.setLabelProvider(runtimeTypeFixedLabelProvider);
descriptorList.add(descriptor);
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.properties.IPropertySource#getEditableValue()
*/
@Override
public Object getEditableValue() {
return delegate.getEditableValue();
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
*/
@Override
public IPropertyDescriptor[] getPropertyDescriptors() {
if(descriptorList.isEmpty()) {
updateDescriptorList();
}
IPropertyDescriptor[] emfDescriptors = delegate.getPropertyDescriptors();
IPropertyDescriptor[] result = new IPropertyDescriptor[emfDescriptors.length + descriptorList.size()];
int index = 0;
for ( ; index<emfDescriptors.length ; ++index ) {
result[index] = emfDescriptors[index];
}
for ( Iterator nodeIter = descriptorList.iterator() ; nodeIter.hasNext() ; ++index ) {
result[index] = (IPropertyDescriptor) nodeIter.next();
}
return result;
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
*/
@Override
public Object getPropertyValue(Object id) {
if (id instanceof Node) {
Object value = ((Node) id).getNodeValue();
String nodeName = ((Node) id).getNodeName();
if (nodeName.equals(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME)) {
// runtime type value must return an integer in the list so the combo box works. stupid, huh?
value = new Integer(findValueInArray(runtimeTypeArray, value));
} else if (nodeName.equals(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME)) {
value = new Integer(findValueInArray(runtimeTypeFixedArray, value));
}
return value;
}
return delegate.getPropertyValue(id);
}
private int findValueInArray(Object[] array, Object value) {
if (array != null && value != null) {
for (int i = 0; i < array.length; i++) {
if (array[i].equals(value)) {
return i;
}
}
}
return -1;
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object)
*/
@Override
public boolean isPropertySet(Object id) {
if ( id instanceof Node ) {
return ((Node) id).getNodeValue() != null;
}
return delegate.isPropertySet(id);
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object)
*/
@Override
public void resetPropertyValue(Object id) {
if (id instanceof Node) {
setPropertyValue(id, null);
((Node) id).setNodeValue(null);
} else {
boolean started = ModelerCore.startTxn(ModelObjectPropertySource.SET + id.toString(), this);
boolean succeeded = false;
try {
delegate.resetPropertyValue(id);
succeeded = true;
} finally {
if (started) {
if ( succeeded ) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
*/
@Override
public void setPropertyValue(Object id, Object value) {
boolean started = ModelerCore.startTxn(ModelObjectPropertySource.SET + id.toString(), this);
boolean succeeded = false;
try {
if (id instanceof Node) {
final Object owner = this.delegate.getEditableValue();
// The owning object should be a simple type, as nodes are used only when we're dealing
// with enterprise attributes (remnants from the enterprise extensions formerly existing
// as attributes in the annonation's application information tag). We only allow editing
// of the runtime type and runtime type fixed (no uuid modifications). If the key of the node
// is not one of these two's attribute name, we will do nothing.
if (owner instanceof XSDSimpleTypeDefinition) {
XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition) ModelObjectUtilities.getRealEObject((XSDSimpleTypeDefinition) owner);
EnterpriseDatatypeInfo edtInfo = ModelerCore.getDatatypeManager(simpleType).getEnterpriseDatatypeInfo(simpleType);
String nodeName = ((Node) id).getNodeName();
boolean isValidSet = false;
String newValue = ""; //$NON-NLS-1$
if (nodeName.equals(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME)) {
// runtime type value must convert from Integer to String
// because that's how the combo box works. stupid, huh?
edtInfo.setRuntimeType(value != null ? this.runtimeTypeLabelProvider.getText(value) : ""); //$NON-NLS-1$
newValue = edtInfo.getRuntimeType();
isValidSet = true;
} else if (nodeName.equals(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME)) {
edtInfo.setRuntimeTypeFixed(Boolean.valueOf(value != null ? this.runtimeTypeFixedLabelProvider.getText(value) : "")); //$NON-NLS-1$
newValue = edtInfo.getRuntimeTypeFixed().toString();
isValidSet = true;
}
if (isValidSet) {
ModelerCore.getModelEditor().setEnterpriseDatatypePropertyValue(simpleType, edtInfo);
((Node) id).setNodeValue(newValue);
}
}
} else {
delegate.setPropertyValue(id, value);
}
succeeded = true;
} finally {
if ( started ) {
if ( succeeded ) {
ModelerCore.commitTxn();
} else {
ModelerCore.rollbackTxn();
}
}
}
}
}