blob: d6d120b2524833921ae6ed36ab28e748b101b7a9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Red Hat, Inc.
* All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
*
* @author Bob Brodt
******************************************************************************/
package org.eclipse.bpmn2.modeler.core.adapters;
import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
import org.eclipse.emf.ecore.resource.Resource;
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.ComposeableAdapterFactory;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
/**
* @author Bob Brodt
*
*/
public class ObjectDescriptor<T extends EObject> {
protected T object;
protected String label;
protected String name;
protected AdapterFactory adapterFactory;
public ObjectDescriptor(AdapterFactory adapterFactory, T object) {
this.object = object;
}
public void setLabel(String label) {
this.label = label;
}
public String getLabel(Object context) {
EObject object = (context instanceof EObject) ?
(EObject)context :
this.object;
EClass eclass = (object instanceof EClass) ?
(EClass)object :
object.eClass();
if (label==null) {
label = ModelUtil.toDisplayName(eclass.getName());
}
return label;
}
public void setDisplayName(String name) {
this.name = name;
}
public String getDisplayName(Object context) {
if (name==null) {
T object = adopt(context);
// derive text from feature's value: default behavior is
// to use the "name" attribute if there is one;
// if not, use the "id" attribute;
// fallback is to use the feature's toString()
String text = ModelUtil.toDisplayName(object.eClass().getName());
Object value = null;
EStructuralFeature f = null;
f = object.eClass().getEStructuralFeature("name");
if (f!=null) {
value = object.eGet(f);
if (value==null || value.toString().isEmpty())
value = null;
}
if (value==null) {
f = object.eClass().getEStructuralFeature("id");
if (f!=null) {
value = object.eGet(f);
if (value==null || value.toString().isEmpty())
value = null;
}
}
if (value==null)
value = "Unnamed " + text;
return (String)value;
}
return name;
}
protected IItemPropertyDescriptor getPropertyDescriptor(EStructuralFeature feature) {
return getPropertyDescriptor(object, feature);
}
protected IItemPropertyDescriptor getPropertyDescriptor(T object, EStructuralFeature feature) {
ItemProviderAdapter adapter = null;
for (Adapter a : object.eAdapters()) {
if (a instanceof ItemProviderAdapter) {
adapter = (ItemProviderAdapter)a;
break;
}
}
if (adapter!=null)
return adapter.getPropertyDescriptor(object, feature);
return null;
}
protected EObject clone(T oldObject) {
T newObject = null;
if (oldObject!=null) {
EClass eClass = oldObject.eClass();
newObject = (T) eClass.getEPackage().getEFactoryInstance().create(eClass);
for (EStructuralFeature f : eClass.getEAllAttributes()) {
newObject.eSet(f, oldObject.eGet(f));
}
}
return newObject;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof EObject && ((EObject) obj).eClass() == object.eClass()) {
// compare feature values of both EObjects:
// this should take care of most of the BPMN2 elements
for (EStructuralFeature f : object.eClass().getEAllStructuralFeatures()) {
// IDs are allowed to be different
if ("id".equals(f.getName()))
continue;
Object v1 = ((T)obj).eGet(f);
Object v2 = object.eGet(f);
// both null? equal!
if (v1==null && v2==null)
continue;
// one or the other null? not equal!
if (v1==null || v2==null)
return false;
// both not null? do a default compare...
if (!v1.equals(v2)) {
// the default Object.equals(obj) fails:
// for Dynamic EObjects (used here as "proxies") only compare their proxy URIs
if (v1 instanceof DynamicEObjectImpl && v2 instanceof DynamicEObjectImpl) {
v1 = ((DynamicEObjectImpl)v1).eProxyURI();
v2 = ((DynamicEObjectImpl)v2).eProxyURI();
if (v1==null && v2==null)
continue;
if (v1==null || v2==null)
return false;
if (v1.equals(v2))
continue;
}
else if (v1 instanceof EObject && v2 instanceof EObject) {
// for all other EObjects, do a deep compare...
ExtendedPropertiesAdapter<T> adapter = (ExtendedPropertiesAdapter<T>) AdapterUtil.adapt((EObject)v1, ExtendedPropertiesAdapter.class);
if (adapter!=null) {
if (adapter.getObjectDescriptor().equals(v2))
continue;
}
}
return false;
}
}
return true;
}
return super.equals(obj);
}
/**
* Many methods accept java Objects as a context variable. In many cases (especially the
* default implementations) the context object must have the same type as the specialized
* class.
*
* @param context
* @return the context variable if it has the same type as this.object, or this.object if not.
*/
protected T adopt(Object context) {
return (this.object.getClass().isInstance(context)) ? (T)context : this.object;
}
public TransactionalEditingDomain getEditingDomain(Object context) {
T object = adopt(context);
EditingDomain result = AdapterFactoryEditingDomain.getEditingDomainFor(object);
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();
}
}
}
if (result instanceof TransactionalEditingDomain)
return (TransactionalEditingDomain)result;
return null;
}
public T createObject(Object context) {
return createObject(null,context);
}
public T createObject(Resource resource, Object context) {
EClass eClass = null;
if (context instanceof EClass) {
eClass = (EClass)context;
}
else if (context instanceof EObject) {
eClass = ((EObject)context).eClass();
if (resource==null)
resource = ((EObject)context).eResource();
}
else {
eClass = object.eClass();
}
assert(object.eClass().isSuperTypeOf(eClass));
T newObject = (T) eClass.getEPackage().getEFactoryInstance().create(eClass);
if (resource==null)
resource = object.eResource();
// if the object has an "id", assign it now.
String id = ModelUtil.setID(newObject,resource);
// also set a default name
EStructuralFeature feature = newObject.eClass().getEStructuralFeature("name");
if (feature!=null) {
if (id!=null)
newObject.eSet(feature, ModelUtil.toDisplayName(id));
else
newObject.eSet(feature, "New "+ModelUtil.toDisplayName(newObject.eClass().getName()));
}
return newObject;
}
}