/**
* Copyright (c) 2002-2006 IBM Corporation and others.
* 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:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.edit.provider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.common.util.ResourceLocator;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
import org.eclipse.emf.edit.EMFEditPlugin;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor.OverrideableCommandOwner;
/**
* This implementation of an item property descriptor supports delegating of the {@link IItemPropertySource} interface
* to the {@link IItemPropertyDescriptor} interface.
*/
public class ItemPropertyDescriptor implements IItemPropertyDescriptor, OverrideableCommandOwner
{
/**
* Returns the feature's default {@link #getId(Object) identifier}.
* @param eStructuralFeature the feature to lookup.
* @return the feature's default identifier.
*/
public static String getDefaultId(EStructuralFeature eStructuralFeature)
{
return eStructuralFeature.getName();
}
public static final Object BOOLEAN_VALUE_IMAGE = EMFEditPlugin.INSTANCE.getImage("full/obj16/BooleanValue");
public static final Object GENERIC_VALUE_IMAGE = EMFEditPlugin.INSTANCE.getImage("full/obj16/GenericValue");
public static final Object INTEGRAL_VALUE_IMAGE = EMFEditPlugin.INSTANCE.getImage("full/obj16/IntegralValue");
public static final Object REAL_VALUE_IMAGE = EMFEditPlugin.INSTANCE.getImage("full/obj16/RealValue");
public static final Object TEXT_VALUE_IMAGE = EMFEditPlugin.INSTANCE.getImage("full/obj16/TextValue");
/**
* For now we need to keep track of the adapter factory, because we need it to provide a correct label provider.
*/
protected AdapterFactory adapterFactory;
/**
* This is used to locate resources for translated values like enumeration literals.
*/
protected ResourceLocator resourceLocator;
/**
* This is a convenient wrapper of the {@link #adapterFactory}.
*/
protected AdapterFactoryItemDelegator itemDelegator;
/**
* This is returned by {@link #canSetProperty}.
*/
protected boolean isSettable;
/**
* This is the name that is displayed in the property sheet.
*/
protected String displayName;
/**
* This is the description shown in the property sheet when this property is selected.
*/
protected String description;
/**
* This is the structural feature that provides the values for this property.
* This is mutually exclusive with {@link #parentReferences}.
*/
protected EStructuralFeature feature;
/**
* This is the set of single-valued references that act as a parent, only one can have a non null value at a time.
* This is mutually exclusive with {@link #feature}.
*/
protected EReference [] parentReferences;
/**
* Whether the value of this property consists of multi-line text.
* @since 2.2.0
*/
protected boolean multiLine;
/**
* Whether the choices for this property should be sorted for display.
* @since 2.2.0
*/
protected boolean sortChoices;
/**
* This represents the group of properties into which this one should be placed.
*/
protected String category;
/**
* These are the flags used as filters in the property sheet.
*/
protected String [] filterFlags;
/**
* This is the label provider used to render property values.
*/
// protected Object labelProvider;
/**
* This is the image that will be used with the value no matter what type of object it is.
*/
protected Object staticImage;
/**
* If non-null, this object will be the owner of commands created to set the property's value.
*/
protected Object commandOwner;
/**
* This class uses a static image
*/
protected class ItemDelegator extends AdapterFactoryItemDelegator
{
protected ResourceLocator resourceLocator;
public ItemDelegator(AdapterFactory adapterFactory)
{
super(adapterFactory);
}
public ItemDelegator(AdapterFactory adapterFactory, ResourceLocator resourceLocator)
{
super(adapterFactory);
this.resourceLocator = resourceLocator;
}
@Override
public String getText(Object object)
{
if (feature instanceof EAttribute)
{
EDataType eDataType = ((EAttribute)feature).getEAttributeType();
if (eDataType.isSerializable() && (eDataType != EcorePackage.Literals.EJAVA_OBJECT || !feature.isTransient()))
{
if (isMany(object))
{
if (object instanceof List<?>)
{
StringBuffer result = new StringBuffer();
for (Iterator<?> i = ((List<?>)object).iterator(); i.hasNext(); )
{
Object value = i.next();
result.append(convert(eDataType, value));
if (i.hasNext())
{
result.append(", ");
}
}
return result.toString();
}
}
if (eDataType.isInstance(object))
{
return convert(eDataType, object);
}
}
}
return super.getText(object);
}
protected String convert(EDataType eDataType, Object value)
{
if (resourceLocator != null)
{
if (eDataType instanceof EEnum)
{
try
{
return
resourceLocator.getString
("_UI_" + eDataType.getName() + "_" + ((Enumerator)value).getName() + "_literal");
}
catch (MissingResourceException exception)
{
// Ignore
}
}
else if (value instanceof Boolean)
{
try
{
return
resourceLocator.getString
(Boolean.TRUE.equals(value) ? "_UI_Boolean_true_literal" : "_UI_Boolean_false_literal");
}
catch (MissingResourceException exception)
{
// Ignore
}
}
}
return crop(EcoreUtil.convertToString(eDataType, value));
}
// This is copied from ItemProviderAdapterFactory.
//
protected String crop(String text)
{
if (text != null)
{
char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++)
{
if (Character.isISOControl(chars[i]))
{
return text.substring(0, i) + "...";
}
}
}
return text;
}
@Override
public Object getImage(Object object)
{
return staticImage == null ? super.getImage(object) : staticImage;
}
}
/**
* This creates an instance that does not use a resource locator and determines the cell editor from the type of the
* structural feature. It assumed that the feature should be settable from this property.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature)
{
this(adapterFactory, null, displayName, description, feature, true, false, false, null, null, null);
}
/**
* This creates an instance that uses a resource locator and determines the cell editor from the type of the
* structural feature. It assumed that the feature should be settable from this property.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature)
{
this(adapterFactory, resourceLocator, displayName, description, feature, true, false, false, null, null, null);
}
/**
* This creates an instance that does not use a resource locator and determines the cell editor from the type of the
* structural feature.
*
* <p>To reduce the number of constructors for this class, this one may be deprecated in the future. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable)
{
this(adapterFactory, null, displayName, description, feature, isSettable, false, false, null, null, null);
}
/**
* This creates an instance that uses a resource locator and determines the cell editor from the type of the
* structural feature.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable)
{
this(adapterFactory, resourceLocator, displayName, description, feature, isSettable, false, false, null, null, null);
}
/**
* This creates an instance that does not use a resource locator, specifies a static image, and determines the cell
* editor from the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one may be deprecated in the future. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, Object)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
Object staticImage)
{
this(adapterFactory, null, displayName, description, feature, isSettable, false, false, staticImage, null, null);
}
/**
* This creates an instance that uses a resource locator, specifies a static image, and determines the cell editor
* from the type of the structural feature.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
Object staticImage)
{
this(adapterFactory, resourceLocator, displayName, description, feature, isSettable, false, false, staticImage, null, null);
}
/**
* This creates an instance that does not use a resource locator, specifies a category, and determines the cell
* editor from the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
String category)
{
this(adapterFactory, null, displayName, description, feature, isSettable, false, false, null, category, null);
}
/**
* This creates an instance that uses a resource locator, specifies a category, and determines the cell editor from
* the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
String category)
{
this(adapterFactory, resourceLocator, displayName, description, feature, isSettable, false, false, null, category, null);
}
/**
* This creates an instance that does not use a resource locator, specifies a static image and category, and
* determines the cell editor from the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, boolean, boolean, Object, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
Object staticImage,
String category)
{
this(adapterFactory, null, displayName, description, feature, isSettable, false, false, staticImage, category, null);
}
/**
* This creates an instance that uses a resource locator, specifies a static image and category, and determines the
* cell editor from the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, boolean, boolean, Object, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
Object staticImage,
String category)
{
this(adapterFactory, resourceLocator, displayName, description, feature, isSettable, false, false, staticImage, category, null);
}
/**
* This creates an instance that does not use a resource locator, specifies a category and filter flags, and
* determines the cell editor from the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one may be deprecated in the future. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
String category,
String [] filterFlags)
{
this(adapterFactory, null, displayName, description, feature, isSettable, false, false, null, category, filterFlags);
}
/**
* This creates an instance that uses a resource locator, specifies a category and filter flags, and determines the
* cell editor from the type of the structural feature.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
String category,
String [] filterFlags)
{
this(adapterFactory, resourceLocator, displayName, description, feature, isSettable, false, false, null, category, filterFlags);
}
/**
* This creates an instance that does not use a resource locator; specifies a static image, a category, and filter
* flags; and determines the cell editor from the type of the structural feature.
*
* <p>To reduce the number of constructors for this class, this one may be deprecated in the future. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EStructuralFeature, boolean, boolean, boolean, Object, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
Object staticImage,
String category,
String [] filterFlags)
{
this(adapterFactory, null, displayName, description, feature, isSettable, false, false, staticImage, category, filterFlags);
}
/**
* This creates an instance that uses a resource locator; specifies a static image, a category, and filter flags;
* and determines the cell editor from the type of the structural feature.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
Object staticImage,
String category,
String [] filterFlags)
{
this(adapterFactory, resourceLocator, displayName, description, feature, isSettable, false, false, staticImage, category, filterFlags);
}
/**
* This creates an instance that uses a resource locator; indicates whether to be multi-line and to sort choices; specifies
* a static image, a category, and filter flags; and determines the cell editor from the type of the structural feature.
* @since 2.2.0
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EStructuralFeature feature,
boolean isSettable,
boolean multiLine,
boolean sortChoices,
Object staticImage,
String category,
String [] filterFlags)
{
this.adapterFactory = adapterFactory;
this.resourceLocator = resourceLocator;
this.itemDelegator = new ItemDelegator(adapterFactory, resourceLocator);
this.displayName = displayName;
this.description = description;
this.feature = feature;
this.isSettable = isSettable;
this.multiLine = multiLine;
this.sortChoices = sortChoices;
this.staticImage = staticImage;
this.category = category;
this.filterFlags = filterFlags;
}
/**
* This creates an instance that does not use a resource locator and determines the cell editor from the parent
* references. It assumed that the feature should be settable from this property.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EReference[], boolean)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EReference [] parentReferences)
{
this(adapterFactory, null, displayName, description, parentReferences, true, null, null);
}
/**
* This creates an instance that uses a resource locator and determines the cell editor from the parent references.
* It assumed that the feature should be settable from this property.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EReference[], boolean)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EReference [] parentReferences)
{
this(adapterFactory, resourceLocator, displayName, description, parentReferences, true, null, null);
}
/**
* This creates an instance that does not use a resource locator and determines the cell editor from the parent
* references.
*
* <p>To reduce the number of constructors for this class, this one may be deprecated in the future. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EReference[], boolean)
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EReference [] parentReferences,
boolean isSettable)
{
this(adapterFactory, null, displayName, description, parentReferences, isSettable, null, null);
}
/**
* This creates an instance that uses a resource locator and determines the cell editor from the parent references.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EReference [] parentReferences,
boolean isSettable)
{
this(adapterFactory, resourceLocator, displayName, description, parentReferences, isSettable, null, null);
}
/**
* This creates an instance that does not use a resource locator, specifies a category, and determines the cell
* editor from the parent references.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EReference[], boolean, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EReference [] parentReferences,
boolean isSettable,
String category)
{
this(adapterFactory, null, displayName, description, parentReferences, isSettable, category, null);
}
/**
* This creates an instance that uses a resource locator, specifies a category, and determines the cell editor from
* the parent references.
*
* <p>To reduce the number of constructors for this class, this one will soon be deprecated. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EReference[], boolean, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EReference [] parentReferences,
boolean isSettable,
String category)
{
this(adapterFactory, resourceLocator, displayName, description, parentReferences, isSettable, category, null);
}
/**
* This creates an instance that does not use a resource locator, specifies a category and filter flags, and
* determines the cell editor from the parent references.
*
* <p>To reduce the number of constructors for this class, this one may be deprecated in the future. For new code, please
* use {@link #ItemPropertyDescriptor(AdapterFactory, ResourceLocator, String, String, EReference[], boolean, String, String[])
* this} form, instead.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
String displayName,
String description,
EReference [] parentReferences,
boolean isSettable,
String category,
String [] filterFlags)
{
this(adapterFactory, null, displayName, description, parentReferences, isSettable, category, filterFlags);
}
/**
* This creates an instance that uses a resource locator, specifies a category and filter flags, and determines the
* cell editor from the parent references.
*/
public ItemPropertyDescriptor
(AdapterFactory adapterFactory,
ResourceLocator resourceLocator,
String displayName,
String description,
EReference [] parentReferences,
boolean isSettable,
String category,
String [] filterFlags)
{
this.adapterFactory = adapterFactory;
this.resourceLocator = resourceLocator;
this.itemDelegator = new ItemDelegator(adapterFactory, resourceLocator);
this.displayName = displayName;
this.description = description;
this.parentReferences = parentReferences;
this.isSettable = isSettable;
this.category = category;
this.filterFlags = filterFlags;
}
/**
* This returns the group of properties into which this one should be placed.
*/
public String getCategory(Object object)
{
return category;
}
/**
* This returns the description to be displayed in the property sheet when this property is selected.
*/
public String getDescription(Object object)
{
return description;
}
/**
* This returns the name of the property to be displayed in the property sheet.
*/
public String getDisplayName(Object object)
{
return displayName;
}
/**
* This returns the flags used as filters in the property sheet.
*/
public String[] getFilterFlags(Object object)
{
return filterFlags;
}
/**
* This returns the {@link #getDefaultId(EStructuralFeature) default identifier} of the {@link #feature feature}
* if it's present,
* or dash-separated concatenation of the default identifier of each {@link #parentReferences parent reference}.
* This key that must uniquely identify this descriptor
* among the other descriptors from the same {@link IItemPropertySource#getPropertyDescriptor(Object, Object) property source}.
*/
public String getId(Object object)
{
if (feature != null)
{
return getDefaultId(feature);
}
else if (parentReferences != null && parentReferences.length != 0)
{
StringBuffer result = new StringBuffer(getDefaultId(parentReferences[0]));
for (int i = 1; i < parentReferences.length; ++i)
{
result.append('-');
result.append(getDefaultId(parentReferences[i]));
}
return result.toString();
}
else
{
return displayName;
}
}
public Object getHelpContextIds(Object object)
{
return null;
}
protected static final EcorePackage ecorePackage = EcorePackage.eINSTANCE;
/**
* This will be called to populate a list of choices.
* The label provider will be used to determine the labels for the objects this returns.
* This default implementation uses {@link #getReachableObjectsOfType getReachableObjectsOfType}.
*/
protected Collection<?> getComboBoxObjects(Object object)
{
if (object instanceof EObject)
{
EObject eObject = (EObject)object;
EClass eClass = eObject.eClass();
if (parentReferences != null)
{
Collection<Object> result = new UniqueEList<Object>();
for (int i = 0; i < parentReferences.length; ++i)
{
result.addAll(getReachableObjectsOfType(eObject, eClass.getFeatureType(parentReferences[i])));
}
return result;
}
else if (feature != null)
{
EGenericType eGenericType = eClass.getFeatureType(feature);
if (feature instanceof EReference)
{
Collection<EObject> result = getReachableObjectsOfType(eObject, eGenericType);
if (!feature.isMany() && !result.contains(null))
{
result.add(null);
}
return result;
}
else
{
EClassifier eType = eGenericType.getERawType();
if (eType instanceof EEnum)
{
EEnum eEnum = (EEnum)eType;
List<Enumerator> enumerators = new ArrayList<Enumerator>();
for (EEnumLiteral eEnumLiteral : eEnum.getELiterals())
{
enumerators.add(eEnumLiteral.getInstance());
}
return enumerators;
}
else
{
EDataType eDataType = (EDataType)eType;
List<String> enumeration = ExtendedMetaData.INSTANCE.getEnumerationFacet(eDataType);
if (!enumeration.isEmpty())
{
List<Object> enumerators = new ArrayList<Object>();
for (String enumerator : enumeration)
{
enumerators.add(EcoreUtil.createFromString(eDataType, enumerator));
}
return enumerators;
}
else
{
for (EDataType baseType = ExtendedMetaData.INSTANCE.getBaseType(eDataType);
baseType != null;
baseType = ExtendedMetaData.INSTANCE.getBaseType(baseType))
{
if (baseType instanceof EEnum)
{
EEnum eEnum = (EEnum)baseType;
List<Enumerator> enumerators = new ArrayList<Enumerator>();
enumerators.add(null);
for (EEnumLiteral eEnumLiteral : eEnum.getELiterals())
{
enumerators.add(eEnumLiteral.getInstance());
}
return enumerators;
}
}
}
}
}
}
}
return null;
}
/**
* This yields all reachable references from object with a meta object which indicates that it is a subtype of type.
*/
static public Collection<EObject> getReachableObjectsOfType(EObject object, EClassifier type)
{
LinkedList<EObject> itemQueue = new LinkedList<EObject>();
Collection<EObject> visited = new HashSet<EObject>();
Collection<EObject> result = new ArrayList<EObject>();
Resource resource = object.eResource();
if (resource != null)
{
ResourceSet resourceSet = resource.getResourceSet();
if (resourceSet != null)
{
for (TreeIterator<?> i = resourceSet.getAllContents(); i.hasNext(); )
{
Object child = i.next();
if (child instanceof EObject)
{
collectReachableObjectsOfType(visited, itemQueue, result, (EObject)child, type);
i.prune();
}
}
}
else
{
for (EObject eObject : resource.getContents())
{
collectReachableObjectsOfType(visited, itemQueue, result, eObject, type);
}
}
}
else
{
collectReachableObjectsOfType(visited, itemQueue, result, EcoreUtil.getRootContainer(object), type);
}
while (!itemQueue.isEmpty())
{
EObject nextItem = itemQueue.removeFirst();
collectReachableObjectsOfType(visited, itemQueue, result, nextItem, type);
}
return result;
}
/**
* This will visit all reachable references from object except those in visited;
* it updates visited and adds to result any object with a meta object that indicates that it is a subtype of type.
*/
static public void collectReachableObjectsOfType(Collection<EObject> visited, Collection<EObject> result, EObject object, EClassifier type)
{
LinkedList<EObject> itemQueue = new LinkedList<EObject>();
collectReachableObjectsOfType(visited, itemQueue, result, object, type);
while (!itemQueue.isEmpty())
{
EObject nextItem = itemQueue.removeFirst();
collectReachableObjectsOfType(visited, itemQueue, result, nextItem, type);
}
}
/**
* This will visit all reachable references from object except those in visited and add them to the queue.
* The queue is processed outside this recursive traversal to avoid stack overflows.
* It updates visited and adds to result any object with a meta object that indicates that it is a subtype of type.
*/
static private void collectReachableObjectsOfType
(Collection<EObject> visited, LinkedList<EObject> itemQueue, Collection<EObject> result, EObject object, EClassifier type)
{
if (visited.add(object))
{
if (type.isInstance(object))
{
result.add(object);
}
// Don't traverse the structure of the EcorePackage's EObject EClass instance.
// This avoids pulling in all the EcorePackage's meta data simply because EObject was used.
//
if (object != EcorePackage.Literals.EOBJECT)
{
EClass eClass = object.eClass();
for (EStructuralFeature eStructuralFeature : eClass.getEAllStructuralFeatures())
{
if (!eStructuralFeature.isDerived())
{
if (eStructuralFeature instanceof EReference)
{
EReference eReference = (EReference)eStructuralFeature;
if (eReference.isMany())
{
@SuppressWarnings("unchecked")
List<EObject> list = ((List<EObject>)object.eGet(eReference));
itemQueue.addAll(list);
}
else
{
EObject eObject = (EObject)object.eGet(eReference);
// Explicitly exclude walking up the container reference for EClassifiers of the EcorePackage instance
// except for EClass instances (other than EObject which was excluded above already).
// This avoids pulling in all the EcorePackage's meta data simply because an EDataType was used.
//
if (eObject != null &&
(eObject != EcorePackage.eINSTANCE ||
eStructuralFeature != EcorePackage.Literals.ECLASSIFIER__EPACKAGE ||
object instanceof EClass))
{
itemQueue.addLast(eObject);
}
}
}
else if (FeatureMapUtil.isFeatureMap(eStructuralFeature))
{
for (FeatureMap.Entry entry : (FeatureMap)object.eGet(eStructuralFeature))
{
if (entry.getEStructuralFeature() instanceof EReference && entry.getValue() != null)
{
itemQueue.addLast((EObject)entry.getValue());
}
}
}
}
}
}
}
}
/**
* This yields all reachable references from object with a meta object which indicates that it is a subtype of type.
* @since 2.9
*/
static public Collection<EObject> getReachableObjectsOfType(EObject object, EGenericType type)
{
LinkedList<EObject> itemQueue = new LinkedList<EObject>();
Collection<EObject> visited = new HashSet<EObject>();
Collection<EObject> result = new ArrayList<EObject>();
Map<EClass, Boolean> subtypes = new HashMap<EClass, Boolean>();
Resource resource = object.eResource();
if (resource != null)
{
ResourceSet resourceSet = resource.getResourceSet();
if (resourceSet != null)
{
for (TreeIterator<?> i = resourceSet.getAllContents(); i.hasNext(); )
{
Object child = i.next();
if (child instanceof EObject)
{
collectReachableObjectsOfType(visited, itemQueue, subtypes, result, (EObject)child, type);
i.prune();
}
}
}
else
{
for (EObject eObject : resource.getContents())
{
collectReachableObjectsOfType(visited, itemQueue, subtypes, result, eObject, type);
}
}
}
else
{
collectReachableObjectsOfType(visited, itemQueue, subtypes, result, EcoreUtil.getRootContainer(object), type);
}
while (!itemQueue.isEmpty())
{
EObject nextItem = itemQueue.removeFirst();
collectReachableObjectsOfType(visited, itemQueue, subtypes, result, nextItem, type);
}
return result;
}
/**
* This will visit all reachable references from object except those in visited;
* it updates visited and adds to result any object with a meta object that indicates that it is a subtype of type.
* @since 2.9
*/
static public void collectReachableObjectsOfType(Collection<EObject> visited, Collection<EObject> result, EObject object, EGenericType type)
{
LinkedList<EObject> itemQueue = new LinkedList<EObject>();
Map<EClass, Boolean> subtypes = new HashMap<EClass, Boolean>();
collectReachableObjectsOfType(visited, itemQueue, subtypes, result, object, type);
while (!itemQueue.isEmpty())
{
EObject nextItem = itemQueue.removeFirst();
collectReachableObjectsOfType(visited, itemQueue, subtypes, result, nextItem, type);
}
}
/**
* This will visit all reachable references from object except those in visited and add them to the queue.
* The queue is processed outside this recursive traversal to avoid stack overflows.
* It updates visited and adds to result any object with a meta object that indicates that it is a subtype of type.
* @since 2.9
*/
static private void collectReachableObjectsOfType
(Collection<EObject> visited, LinkedList<EObject> itemQueue, Map<EClass, Boolean> subtypes, Collection<EObject> result, EObject object, EGenericType type)
{
if (visited.add(object))
{
EClass eClass = object.eClass();
Boolean isInstance = subtypes.get(eClass);
if (isInstance == null)
{
isInstance = type.isInstance(object) ? Boolean.TRUE : Boolean.FALSE;
subtypes.put(eClass, isInstance);
}
if (isInstance == Boolean.TRUE)
{
result.add(object);
}
// Don't traverse the structure of the EcorePackage's EObject EClass instance.
// This avoids pulling in all the EcorePackage's meta data simply because EObject was used.
//
if (object != EcorePackage.Literals.EOBJECT)
{
for (EStructuralFeature eStructuralFeature : eClass.getEAllStructuralFeatures())
{
if (!eStructuralFeature.isDerived())
{
if (eStructuralFeature instanceof EReference)
{
EReference eReference = (EReference)eStructuralFeature;
if (eReference.isMany())
{
@SuppressWarnings("unchecked")
List<EObject> list = ((List<EObject>)object.eGet(eReference));
itemQueue.addAll(list);
}
else
{
EObject eObject = (EObject)object.eGet(eReference);
// Explicitly exclude walking up the container reference for EClassifiers of the EcorePackage instance
// except for EClass instances (other than EObject which was excluded above already).
// This avoids pulling in all the EcorePackage's meta data simply because an EDataType was used.
//
if (eObject != null &&
(eObject != EcorePackage.eINSTANCE ||
eStructuralFeature != EcorePackage.Literals.ECLASSIFIER__EPACKAGE ||
object instanceof EClass))
{
itemQueue.addLast(eObject);
}
}
}
else if (FeatureMapUtil.isFeatureMap(eStructuralFeature))
{
for (FeatureMap.Entry entry : (FeatureMap)object.eGet(eStructuralFeature))
{
if (entry.getEStructuralFeature() instanceof EReference && entry.getValue() != null)
{
itemQueue.addLast((EObject)entry.getValue());
}
}
}
}
}
}
}
}
/**
* This returns the label provider that will be used to render the value of this property.
* The implementation here just creates an {@link AdapterFactoryItemDelegator}.
*/
public IItemLabelProvider getLabelProvider(Object object)
{
return itemDelegator;
}
/**
* This indicates whether these two property descriptors are equal.
* It's not really clear to me how this is meant to be used,
* but it's a little bit like an equals test.
*/
public boolean isCompatibleWith(Object object, Object anotherObject, IItemPropertyDescriptor anotherItemPropertyDescriptor)
{
/*
if (propertyDescriptor == this)
{
return true;
}
else if (propertyDescriptor instanceof ItemPropertyDescriptor)
{
ItemPropertyDescriptor itemPropertyDescriptor = (ItemPropertyDescriptor)propertyDescriptor;
if (adapterFactory == itemPropertyDescriptor.adapterFactory &&
displayName.equals(itemPropertyDescriptor.displayName) &&
(category == null && itemPropertyDescriptor.category == null || category.equals(itemPropertyDescriptor.category)))
{
return true;
}
}
*/
return false;
}
static public class PropertyValueWrapper implements IItemLabelProvider, IItemPropertySource
{
protected Object object;
protected Object propertyValue;
protected Object nestedPropertySource;
protected AdapterFactoryItemDelegator itemDelegator;
public PropertyValueWrapper(AdapterFactory adapterFactory, Object object, Object propertyValue, Object nestedPropertySource)
{
this.object = object;
this.propertyValue = propertyValue;
this.nestedPropertySource = nestedPropertySource;
this.itemDelegator = new AdapterFactoryItemDelegator(adapterFactory);
}
public String getText(Object thisObject)
{
return itemDelegator.getText(propertyValue);
}
public Object getImage(Object thisObject)
{
return itemDelegator.getImage(propertyValue);
}
public List<IItemPropertyDescriptor> getPropertyDescriptors(Object thisObject)
{
// This guards the switch.
//
List<IItemPropertyDescriptor> list = itemDelegator.getPropertyDescriptors(nestedPropertySource);
if (list != null)
{
List<IItemPropertyDescriptor> result = new ArrayList<IItemPropertyDescriptor>(list.size());
for (IItemPropertyDescriptor itemPropertyDescriptor : list)
{
result.add(createPropertyDescriptorDecorator(nestedPropertySource, itemPropertyDescriptor));
}
return result;
}
return Collections.emptyList();
}
public IItemPropertyDescriptor getPropertyDescriptor(Object thisObject, Object propertyId)
{
return
createPropertyDescriptorDecorator(nestedPropertySource, itemDelegator.getPropertyDescriptor(nestedPropertySource, propertyId));
}
public Object getEditableValue(Object thisObject)
{
return propertyValue;
}
protected IItemPropertyDescriptor createPropertyDescriptorDecorator(Object object, IItemPropertyDescriptor itemPropertyDescriptor)
{
return new ItemPropertyDescriptorDecorator(object, itemPropertyDescriptor);
}
}
protected Object createPropertyValueWrapper(Object object, Object propertyValue)
{
return new PropertyValueWrapper(adapterFactory, object, propertyValue, null);
}
public static Object getDefaultValue(EClassifier eType)
{
if (eType.getEPackage() == EcorePackage.eINSTANCE)
{
switch (eType.getClassifierID())
{
case EcorePackage.EBOOLEAN:
case EcorePackage.EBOOLEAN_OBJECT:
{
return Boolean.FALSE;
}
case EcorePackage.EBYTE:
case EcorePackage.EBYTE_OBJECT:
{
return (byte)0;
}
case EcorePackage.ECHAR:
case EcorePackage.ECHARACTER_OBJECT:
{
return ' ';
}
case EcorePackage.EDOUBLE:
case EcorePackage.EDOUBLE_OBJECT:
{
return 0.0;
}
case EcorePackage.EFLOAT:
case EcorePackage.EFLOAT_OBJECT:
{
return 0.0F;
}
case EcorePackage.EINT:
case EcorePackage.EINTEGER_OBJECT:
{
return 0;
}
case EcorePackage.ELONG:
case EcorePackage.ELONG_OBJECT:
{
return 0L;
}
case EcorePackage.ESHORT:
case EcorePackage.ESHORT_OBJECT:
{
return (short)0;
}
case EcorePackage.ESTRING:
{
return "";
}
}
}
else if (eType instanceof EEnum)
{
return (((EEnum)eType).getELiterals().get(0)).getInstance();
}
else if (eType instanceof EDataType)
{
EDataType eDataType = (EDataType)eType;
List<String> enumeration = ExtendedMetaData.INSTANCE.getEnumerationFacet(eDataType);
if (!enumeration.isEmpty())
{
return EcoreUtil.createFromString(eDataType, enumeration.get(0));
}
}
return null;
}
/**
* This is called by {@link #getPropertyValue getPropertyValue} to reflectively obtain the value of a feature
* from an object. It can be overridden by a subclass to provide additional processing of the value.
*/
protected Object getValue(EObject object, EStructuralFeature feature)
{
try
{
return object.eGet(feature);
}
catch (Throwable exception)
{
return null;
}
}
/**
* This does the delegated job of getting the property value from the given object;
* and it sets object, which is necessary if {@link #getComboBoxObjects getComboBoxObjects} is called.
* It is implemented in a generic way using the structural feature or parent references.
*/
public Object getPropertyValue(Object object)
{
EObject eObject = (EObject)object;
if (feature instanceof EAttribute)
{
EAttribute attribute = (EAttribute)feature;
Object result = getValue(eObject, attribute);
// We used to use getDefaultValue() when null, but that behaviour isn't correct: the value is already set to
// its default initially, and we should always show the actual state of the object (bug 102557).
//
if (result == null)
{
//return getDefaultValue(attribute.getEType());
return null;
}
else
{
return createPropertyValueWrapper(object, result);
}
}
else if (parentReferences != null)
{
for (int i = 0; i < parentReferences.length; ++i)
{
Object result = getValue(eObject, parentReferences[i]);
if (result != null)
{
return createPropertyValueWrapper(object, result);
}
}
return "";
}
else
{
return createPropertyValueWrapper(object, getValue(eObject, feature));
}
}
/**
* This does the delegated job of determine whether the property value from the given object is set.
* It is implemented in a generic way using the structural feature.
*/
public boolean isPropertySet(Object object)
{
// System.out.println("isPropertySet " + object);
EObject eObject = (EObject)object;
if (parentReferences != null)
{
for (int i = 0; i < parentReferences.length; ++i)
{
if (eObject.eGet(parentReferences[i]) != null)
{
return true;
}
}
return false;
}
else
{
try
{
return
feature instanceof EAttribute ?
feature.isMany() ?
!((List<?>)eObject.eGet(feature)).isEmpty() :
eObject.eIsSet(feature) :
eObject.eGet(feature) != null;
}
catch (Throwable exception)
{
return false;
}
}
}
/**
* This determines whether this descriptor's property for the object supports set (and reset).
*/
public boolean canSetProperty(Object object)
{
if (isSettable)
{
EditingDomain editingDomain = getEditingDomain(object);
if (editingDomain != null)
{
Resource resource = object instanceof EObject ?
((EObject)object).eResource() :
object instanceof Resource ?
(Resource)object :
null;
return resource == null || !editingDomain.isReadOnly(resource);
}
else
{
return true;
}
}
else
{
return false;
}
}
/**
* Sets the object to use as the owner of commands created to set the property's value.
*/
public void setCommandOwner(Object commandOwner)
{
this.commandOwner = commandOwner;
}
/**
* Returns the override command owner set via {@link #setCommandOwner setCommandOwner}.
*/
public Object getCommandOwner()
{
return commandOwner;
}
/**
* Returns either the override command owner set via {@link #setCommandOwner setCommandOwner} or, if that is null, the
* fall-back object provided.
*/
protected Object getCommandOwner(Object fallback)
{
return commandOwner != null ? commandOwner : fallback;
}
/**
* This does the delegated job of resetting property value back to it's default value.
*/
public void resetPropertyValue(Object object)
{
EObject eObject = (EObject)object;
EditingDomain editingDomain = getEditingDomain(object);
if (parentReferences != null)
{
for (int i = 0; i < parentReferences.length; ++i)
{
final EReference parentReference = parentReferences[i];
if (eObject.eIsSet(parentReference))
{
if (editingDomain == null)
{
eObject.eUnset(parentReferences[i]);
}
else
{
editingDomain.getCommandStack().execute
(SetCommand.create(editingDomain, getCommandOwner(eObject), parentReference, SetCommand.UNSET_VALUE));
}
break;
}
}
}
else
{
if (editingDomain == null)
{
eObject.eUnset(feature);
}
else
{
editingDomain.getCommandStack().execute(SetCommand.create(editingDomain, getCommandOwner(eObject), feature, SetCommand.UNSET_VALUE));
}
}
}
public EditingDomain getEditingDomain(Object object)
{
EObject eObject = (EObject)object;
EditingDomain result = AdapterFactoryEditingDomain.getEditingDomainFor(eObject);
if (result == null)
{
if (adapterFactory instanceof IEditingDomainProvider)
{
result = ((IEditingDomainProvider)adapterFactory).getEditingDomain();
}
if (result == null && adapterFactory instanceof ComposeableAdapterFactory)
{
AdapterFactory rootAdapterFactory = ((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory();
if (rootAdapterFactory instanceof IEditingDomainProvider)
{
result = ((IEditingDomainProvider)rootAdapterFactory).getEditingDomain();
}
}
}
return result;
}
/**
* This does the delegated job of setting the property to the given value.
* It is implemented in a generic way using the structural feature.
*/
public void setPropertyValue(Object object, Object value)
{
EObject eObject = (EObject)object;
EClass eClass = eObject.eClass();
EditingDomain editingDomain = getEditingDomain(object);
if (parentReferences != null)
{
Command removeCommand = null;
for (int i = 0; i < parentReferences.length; ++i)
{
Object oldValue = eObject.eGet(parentReferences[i]);
if (oldValue != null)
{
final EReference parentReference = parentReferences[i];
if (oldValue == value)
{
return;
}
else if (eClass.getFeatureType(parentReference).isInstance(value))
{
if (editingDomain == null)
{
eObject.eSet(parentReference, value);
}
else
{
editingDomain.getCommandStack().execute(SetCommand.create(editingDomain, getCommandOwner(eObject), parentReference, value));
}
return;
}
else
{
if (editingDomain == null)
{
eObject.eSet(parentReference, null);
}
else
{
removeCommand = SetCommand.create(editingDomain, getCommandOwner(eObject), parentReference, null);
}
break;
}
}
}
for (int i = 0; i < parentReferences.length; ++i)
{
final EReference parentReference = parentReferences[i];
if (eClass.getFeatureType(parentReference).isInstance(value))
{
if (editingDomain == null)
{
eObject.eSet(parentReferences[i], value);
}
else
{
if (removeCommand != null)
{
final CompoundCommand compoundCommand = new CompoundCommand(CompoundCommand.LAST_COMMAND_ALL);
compoundCommand.append(removeCommand);
compoundCommand.append(SetCommand.create(editingDomain, getCommandOwner(eObject), parentReference, value));
editingDomain.getCommandStack().execute(compoundCommand);
}
else
{
editingDomain.getCommandStack().execute(SetCommand.create(editingDomain, getCommandOwner(eObject), parentReference, value));
}
}
break;
}
}
}
else
{
if (editingDomain == null)
{
eObject.eSet(feature, value);
}
else
{
editingDomain.getCommandStack().execute(SetCommand.create(editingDomain, getCommandOwner(eObject), feature, value));
}
}
}
public Object getFeature(Object object)
{
if (feature != null)
{
return feature;
}
else if (parentReferences != null)
{
return parentReferences;
}
else
{
return null;
}
}
/**
* Returns whether this property represents multiple values. This is true only if we're using a {@link #feature
* structural feature} to provide the values for this property, and if that feature is multi-valued.
*/
public boolean isMany(Object object)
{
return parentReferences == null && feature != null && feature.isMany();
}
public Collection<?> getChoiceOfValues(Object object)
{
return getComboBoxObjects(object);
}
public boolean isMultiLine(Object object)
{
return multiLine;
}
public boolean isSortChoices(Object object)
{
return sortChoices;
}
}