/*******************************************************************************
 * Copyright (c) 2011, 2012 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 Ivar Meikas
 ******************************************************************************/
package org.eclipse.bpmn2.modeler.core.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.bpmn2.AdHocSubProcess;
import org.eclipse.bpmn2.BaseElement;
import org.eclipse.bpmn2.Bpmn2Factory;
import org.eclipse.bpmn2.Bpmn2Package;
import org.eclipse.bpmn2.Choreography;
import org.eclipse.bpmn2.ChoreographyActivity;
import org.eclipse.bpmn2.Collaboration;
import org.eclipse.bpmn2.Definitions;
import org.eclipse.bpmn2.DocumentRoot;
import org.eclipse.bpmn2.Event;
import org.eclipse.bpmn2.EventDefinition;
import org.eclipse.bpmn2.ExtensionAttributeValue;
import org.eclipse.bpmn2.FormalExpression;
import org.eclipse.bpmn2.Participant;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.RootElement;
import org.eclipse.bpmn2.SubChoreography;
import org.eclipse.bpmn2.SubProcess;
import org.eclipse.bpmn2.Transaction;
import org.eclipse.bpmn2.di.BPMNDiagram;
import org.eclipse.bpmn2.di.BPMNPlane;
import org.eclipse.bpmn2.di.BpmnDiPackage;
import org.eclipse.bpmn2.modeler.core.Activator;
import org.eclipse.bpmn2.modeler.core.adapters.AdapterRegistry;
import org.eclipse.bpmn2.modeler.core.adapters.AdapterUtil;
import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter;
import org.eclipse.bpmn2.modeler.core.adapters.INamespaceMap;
import org.eclipse.bpmn2.modeler.core.adapters.InsertionAdapter;
import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerResourceSetImpl;
import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
import org.eclipse.bpmn2.util.Bpmn2Resource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.dd.dc.DcPackage;
import org.eclipse.dd.di.DiPackage;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
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.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
import org.eclipse.emf.ecore.impl.EAttributeImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.BasicFeatureMap;
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.FeatureMap.Entry;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.platform.IDiagramContainer;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDElementDeclaration;

public class ModelUtil {

	// TODO: need to determine whether IDs need to be unique within a Resource or ResourceSet - see getKey()
	
	// Map of EMF resource sets to ID mapping tables. The ID mapping tables map a BPMN2 element ID string to the EObject.
	// The EObject is not used anywhere (yet!) just a placeholder to allow use of a HashMap for fast lookups of the ID string.
	// The ID strings are composed from the BPMN2 element description name and a sequence number (starting at 1).
	// When a new ID is requested, generateID() simply increments the sequence number until an ID is found that isn't
	// already in the table.
	public static HashMap<Object, Hashtable<String, EObject>> ids = new  HashMap<Object, Hashtable<String, EObject>>();
	// Map of ID strings and sequential counters for each BPMN2 element description.
	public static HashMap<String, Integer> defaultIds = new HashMap<String, Integer>();

	/**
	 * Clear the IDs hashmap for the given EMF Resource. This should be called
	 * when the editor is disposed to avoid unnecessary growth of the IDs table.
	 * 
	 * @param res - the EMF Resource that was used to generate the ID strings.
	 */
	public static void clearIDs(Resource res, boolean all) {
		ids.remove( getKey(res) );
		if (all) {
			defaultIds.clear();
		}
	}

	/**
	 * Construct the first part of the ID string using the BPMN2 element description name.
	 * If the object is a DI element, concatenate the BPMN2 element description name.
	 * 
	 * @param obj - the BPMN2 object
	 * @return name string
	 */
	private static String getObjectName(EObject obj) {
		String name;
		EStructuralFeature feature = ((EObject)obj).eClass().getEStructuralFeature("bpmnElement"); //$NON-NLS-1$
		if (feature!=null && obj.eGet(feature)!=null) {
			EObject bpmnElement = (EObject) obj.eGet(feature);
			name = obj.eClass().getName() + "_" + bpmnElement.eClass().getName(); //$NON-NLS-1$
		}
		else {
			name = obj.eClass().getName();
		}
		return name;
	}
	
	private static Object getKey(EObject obj) {
		Resource resource = getResource(obj);
		if (resource==null) {
//			System.out.println("The object type "+obj.getClass().getName()+" is not contained in a Resource");
			return null;
		}
		Assert.isTrue(obj!=null);
		return getKey(resource);
	}
	
	private static Object getKey(Resource res) {
		Assert.isTrue(res!=null);
		return res.getResourceSet();
	}
	
	/**
	 * If an EObject has not yet been added to a Resource (e.g. during construction)
	 * generate an ID string using a different strategy (basically same ID prefixed with an underscore).
	 * The "defaultIds" table is used to track the next sequential ID value for a given element description.
	 * 
	 * @param obj - the BPMN2 object
	 * @return the ID string
	 */
	private static String generateDefaultID(EObject obj, String name) {
		if (name==null)
			name = getObjectName(obj);
		Integer value = defaultIds.get(name);
		if (value==null)
			value = Integer.valueOf(1);
		value = Integer.valueOf( value.intValue() + 1 );
		defaultIds.put(name, Integer.valueOf(value));
		
		return "_" + name + "_" + value; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Generate an ID string for a given BPMN2 object that will (eventually!) be added to the given Resource.
	 * 
	 * CAUTION: IDs for objects that have already been deleted WILL be reused.
	 * 
	 * @param obj - the BPMN2 object
	 * @param res - the Resource to which the object will be added
	 * @return the ID string
	 */
	private static String generateID(EObject obj, Resource res) {
		return generateID(obj, res, null);
	}

	public static String generateID(EObject obj, Resource res, String name) {
		Object key = (res==null ? getKey(obj) : getKey(res));
		if (key!=null) {
			Hashtable<String, EObject> tab = ids.get(key);
			if (tab==null) {
				tab = new Hashtable<String, EObject>();
				ids.put(key, tab);
			}
			
			String id = name;
			if (name==null) {
				name = getObjectName(obj);
				id = name + "_" + 1; //$NON-NLS-1$
			}
			
			for (int i=1;; ++i) {
				if (tab.get(id)==null) {
					tab.put(id, obj);
					return id;
				}
				id = name + "_" + i; //$NON-NLS-1$
			}
		}
		return generateDefaultID(obj, name);
	}
	
	public static void unsetID(EObject obj, Resource resource) {
		EStructuralFeature feature = ((EObject)obj).eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature!=null) {
			Object value = obj.eGet(feature);
			if (value instanceof String) {
				String id = (String)value;
				Object key = getKey(resource);
				if (key!=null) {
					Hashtable<String, EObject> tab = ids.get(key);
					if (tab!=null) {
						tab.remove(id);
					}
				}
			}
		}
	}
	
	/**
	 * Add an ID string to the ID mapping table(s). This must be used during model import
	 * to add existing BPMN2 element IDs to the table so we don't generate duplicates.
	 * 
	 * @param obj - the BPMN2 object
	 */
	public static void addID(EObject obj) {
		EStructuralFeature feature = ((EObject)obj).eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature!=null) {
			Object value = obj.eGet(feature);
			if (value!=null) {
				addID(obj,(String)value);
			}
			else {
				// TODO: what to do here if the BPMN2 element has an "id" attribute which is not set?
				// should we generate one and set it?
				// yup
				setID(obj);
			}
		}
		
	}
	
	/**
	 * Add an ID string to the ID mapping table(s). This must be used during model import
	 * to add existing BPMN2 element IDs to the table so we don't generate duplicates.
	 * 
	 * @param obj - the BPMN2 object
	 * @param id - the object's ID string
	 */
	public static void addID(EObject obj, String id) {
		Object key = getKey(obj);
		String name = getObjectName(obj);
		if (key==null || id.startsWith("_" + name + "_")) { //$NON-NLS-1$ //$NON-NLS-2$
			int newValue = 0;
			try {
				int i = id.lastIndexOf('_') + 1;
				if (i<id.length())
					newValue = Integer.parseInt(id.substring(i));
			} catch (Exception e) {
			}
			Integer oldValue = defaultIds.get(name);
			if (oldValue==null || newValue > oldValue.intValue())
				defaultIds.put(name, Integer.valueOf(newValue));
		}
		else {	
			Hashtable<String, EObject> tab = ids.get(key);
			if (tab==null) {
				tab = new Hashtable<String, EObject>();
				ids.put(key, tab);
			}
			tab.put(id, obj);
		}
	}

	/**
	 * Generate a unique ID for the given BPMN2 element and set it.
	 * This should only be used during object construction AFTER an object has
	 * already been added to a Resource.
	 * 
	 * @param obj - the BPMN2 object
	 */
	public static String setID(EObject obj) {
		return setID(obj,getResource(obj));
	}

	/**
	 * Generate a unique ID for the given BPMN2 element and set it.
	 * This should be used during object construction if the object has NOT YET
	 * been added to a Resource.
	 * 
	 * @param obj - the BPMN2 object
	 * @param res - the Resource to which the object will be added
	 */
	public static String setID(EObject obj, Resource res) {
		String id = null;
		EStructuralFeature feature = ((EObject)obj).eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature!=null) {
			if (obj.eGet(feature)==null) {
				id = generateID(obj,res);
				obj.eSet(feature, id);
			}
		}
		return id;
	}
	
	public static String getID(EObject obj) {
		EStructuralFeature feature = ((EObject)obj).eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature!=null) {
			return (String)obj.eGet(feature);
		}
		return null;
	}
	
	public static String generateUndefinedID(String base) {
		String name = "undefined"; //$NON-NLS-1$
		if (base.contains("_")) { //$NON-NLS-1$
			return "<" + name + "_" + base.replaceFirst(".*_", "") + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
		}
		
		Integer value = defaultIds.get(name);
		if (value==null)
			value = Integer.valueOf(1);
		value = Integer.valueOf( value.intValue() + 1 );
		defaultIds.put(name, Integer.valueOf(value));
		
		return "<" + name + "_" + value + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	public static int getIDNumber(String id) {
		try {
			int i = id.lastIndexOf("_"); //$NON-NLS-1$
			return Integer.parseInt(id.substring(i+1));
		}
		catch (Exception e) {
			return -1;
		}
	}

	public static String getName(BaseElement element) {
		if (element != null) {
			EStructuralFeature feature = element.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
			if (feature==null)
				feature = getAnyAttribute(element,"name"); //$NON-NLS-1$
			if (feature!=null && element.eGet(feature) instanceof String)
				return (String) element.eGet(feature);
		}
		return null;
	}

	public static boolean hasName(BaseElement obj) {
		EStructuralFeature feature = obj.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
		if (feature==null)
			feature = getAnyAttribute(obj,"name"); //$NON-NLS-1$
		return feature!=null;
	}
/*	
	public static String getLabel(EObject object) {
		if (object==null)
			return "";
		return toDisplayName(object.eClass().getName());
	}
*/	
	public static String toDisplayName(String anyName) {
		// get rid of the "Impl" java suffix
		anyName = anyName.replaceAll("Impl$", ""); //$NON-NLS-1$ //$NON-NLS-2$
		String displayName = ""; //$NON-NLS-1$
		boolean first = true;
		char[] chars = anyName.toCharArray();
		for (int i=0; i<chars.length; ++i) {
			char c = chars[i];
			if (Character.isUpperCase(c)) {
				if (displayName.length()>0 && i+1<chars.length && !Character.isUpperCase(chars[i+1]))
					displayName += " "; //$NON-NLS-1$
			}
			if (first) {
				c = Character.toUpperCase(c);
				first = false;
			}
			if (c=='_')
				c = ' ';
			displayName += c;
		}
		return displayName.trim();
	}

	@SuppressWarnings("unchecked")
	public static List<EventDefinition> getEventDefinitions(Event event) {
		if (event!=null) {
			EStructuralFeature feature = event.eClass().getEStructuralFeature("eventDefinitions"); //$NON-NLS-1$
			if (feature!=null) {
				return (List<EventDefinition>) event.eGet(feature);
			}
		}
		return new ArrayList<EventDefinition>();
	}
	
	/**
	 * Checks if an event has a specific event definition type defined
	 * 
	 * @param event the event to be checked
	 * @param clazz the class of the event definition to 
	 * @return true if the event definition is defined for this event instance, false otherwise
	 */
	public static boolean hasEventDefinition (Event event, Class<?> clazz) {
		for (EventDefinition def : getEventDefinitions(event)) {
			if (clazz.isInstance(def)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Get the first event definition for an given event and given type
	 * 
	 * @param event the event 
	 * @param clazz the event definition class
	 * @return the first event definition definied for this event instance
	 */
	public static EventDefinition getEventDefinition (Event event, Class<?> clazz) {
		for (EventDefinition def : getEventDefinitions(event)) {
			if (clazz.isInstance(def)) {
				return def;
			}
		}
		return null;
	}

	/**
	 * This is a slightly hacked resource set that we will be using for to solve
	 * the problem of loading the right resources from URLs that betray no
	 * information on the type of the resource.
	 * 
	 * @param resourceSet
	 * 
	 * @return the BPMN2ResourceSetImpl that walks around the problem indicated.
	 * 
	 */

	public static Bpmn2ModelerResourceSetImpl slightlyHackedResourceSet(
			ResourceSet resourceSet) {

		if (resourceSet instanceof Bpmn2ModelerResourceSetImpl) {
			return (Bpmn2ModelerResourceSetImpl) resourceSet;
		}

		Map<Object, Object> map = resourceSet.getLoadOptions();
		Bpmn2ModelerResourceSetImpl result = (Bpmn2ModelerResourceSetImpl) map
				.get(Bpmn2ModelerResourceSetImpl.SLIGHTLY_HACKED_KEY);
		if (result == null) {
			result = new Bpmn2ModelerResourceSetImpl();
			map.put(Bpmn2ModelerResourceSetImpl.SLIGHTLY_HACKED_KEY, result);
		}
		return result;
	}

	/**
	 * Return the resource set that we should be using to load "specific" type
	 * of resources. The "slightlyHacked" resource set is kept in the load
	 * options map.
	 * 
	 * @param eObj
	 * @return the slightly hacked resource set.
	 * 
	 */
	public static Bpmn2ModelerResourceSetImpl slightlyHackedResourceSet(EObject eObj) {
		return slightlyHackedResourceSet(eObj.eResource().getResourceSet());
	}
	
	public static Object resolveXSDObject(Object xsdObject) {
		if (xsdObject instanceof XSDElementDeclaration) {
			XSDElementDeclaration resolvedElement = ((XSDElementDeclaration)xsdObject).getResolvedElementDeclaration();
			if (resolvedElement != null) xsdObject = resolvedElement;
		} else if (xsdObject instanceof XSDAttributeDeclaration) {
			XSDAttributeDeclaration resolvedAttribute = ((XSDAttributeDeclaration)xsdObject).getResolvedAttributeDeclaration();
			if (resolvedAttribute != null) xsdObject = resolvedAttribute;
		}
		return xsdObject;
	}

	/**
	 * @param eObject
	 * @return the namespace map for the given object.
	 */

	@SuppressWarnings("unchecked")
	static public INamespaceMap<String, String> getNamespaceMap(EObject eObject) {

		if (eObject == null) {
			throw new NullPointerException(
					"eObject cannot be null in getNamespaceMap()"); //$NON-NLS-1$
		}

		INamespaceMap<String, String> nsMap = null;
    	// Bug 120110 - this eObject may not have a namespace map, but its
		// ancestors might, so keep searching until we find one or until
		// we run out of ancestors.
		while (nsMap==null && eObject!=null) {
			nsMap = AdapterRegistry.INSTANCE.adapt(
				eObject, INamespaceMap.class);
			if (nsMap==null)
				eObject = eObject.eContainer();
		}
		
		if (nsMap == null) {
			throw new IllegalStateException(
					"INamespaceMap cannot be attached to an eObject"); //$NON-NLS-1$
		}

		return nsMap;
	}

	public static String getNamespacePrefix(EObject eObject, String namespace) {

		for (EObject context = eObject; context != null; context = context
				.eContainer()) {
			List<String> pfxList = getNamespaceMap(context).getReverse(
					namespace);
			if (pfxList.size() > 0) {
				return pfxList.get(0);
			}
		}
		return null;
	}
	
	public enum Bpmn2DiagramType {
		NONE("None"), //$NON-NLS-1$
		PROCESS("Process"), //$NON-NLS-1$
		CHOREOGRAPHY("Choreography"), //$NON-NLS-1$
		COLLABORATION("Collaboration"), //$NON-NLS-1$
		CONVERSATION("Conversation"); //$NON-NLS-1$
		String value;
		Bpmn2DiagramType(String value) {
			this.value = value;
		}

		public static Bpmn2DiagramType fromString(String value) {
			if (value != null) {
				for (Bpmn2DiagramType type : Bpmn2DiagramType.values()) {
					if (value.equalsIgnoreCase(type.value)) {
						return type;
					}
				}
			}
			return null;
		}

		@Override
		public String toString() {
			return value;
		}
	}

	public static Bpmn2DiagramType getDiagramType(String name) {
		for (Bpmn2DiagramType t : Bpmn2DiagramType.values()) {
			if (t.toString().equalsIgnoreCase(name))
				return t;
		}
		return Bpmn2DiagramType.NONE;
	}

	public static DiagramEditor getDiagramEditor(EObject object) {
		return getDiagramEditor(getResource(object));
	}
	
	public static DiagramEditor getDiagramEditor(Resource res) {
		if (res != null) {
			for (Adapter a : res.getResourceSet().eAdapters()) {
				if (a instanceof DiagramEditorAdapter) {
					return ((DiagramEditorAdapter)a).getDiagramEditor();
				}
			}
		}
		return null;
	}
	
	public static Bpmn2DiagramType getDiagramType(EObject object) {
		if (object instanceof Diagram) {
			object = BusinessObjectUtil.getBusinessObjectForPictogramElement((Diagram)object);
		}
		if (object instanceof BPMNDiagram)
			return getDiagramType((BPMNDiagram)object);
		DiagramEditor editor = getDiagramEditor(object);
		return getDiagramType(editor);
	}
	
	public static Bpmn2DiagramType getDiagramType(DiagramEditor editor) {
		if (editor!=null) {
			Diagram diagram = editor.getDiagramTypeProvider().getDiagram();
			if (diagram!=null) {
				EObject object = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(diagram);
				if (object instanceof BPMNDiagram)
					return getDiagramType((BPMNDiagram)object);
			}
		}
		return Bpmn2DiagramType.NONE;
	}
	
	public static Bpmn2DiagramType getDiagramType(BPMNDiagram diagram) {
		if (diagram!=null && getResource(diagram)!=null) {
			BPMNPlane plane = diagram.getPlane();
			if (plane!=null) {
				BaseElement be = plane.getBpmnElement();
				if (be==null)
					be = getDefaultBPMNPlaneReference(diagram);
				if (be instanceof Choreography)
					return Bpmn2DiagramType.CHOREOGRAPHY;
				else if (be instanceof Collaboration)
					return Bpmn2DiagramType.COLLABORATION;
				else
					// everything else (like SubProcess, etc.) belongs to a Process diagram
					return Bpmn2DiagramType.PROCESS;
			}
		}
		return Bpmn2DiagramType.NONE;
	}
	
	/**
	 * Return the first Process, SubProcess, AdHocSubProcess, Transaction, Collaboration,
	 * Choreography or SubChoreography defined in this document.
	 * 
	 * @param object
	 * @return
	 */
	public static BaseElement getDefaultBPMNPlaneReference(EObject object) {
		Definitions definitions = getDefinitions(object);
		if (definitions!=null) {
			for (RootElement re : definitions.getRootElements()) {
				if (	re instanceof Process ||
						re instanceof SubProcess ||
						re instanceof AdHocSubProcess ||
						re instanceof Transaction ||
						re instanceof Collaboration ||
						re instanceof Choreography ||
						re instanceof SubChoreography
				) {
					return re;
				}
			}

		}
		return null;
	}
	
	public static String getDiagramTypeName(BPMNDiagram object) {
		Bpmn2DiagramType type = getDiagramType((BPMNDiagram)object); 
		if (type == Bpmn2DiagramType.CHOREOGRAPHY) {
			return Messages.ModelUtil_Choreograpy_Diagram;
		}
		else if (type == Bpmn2DiagramType.COLLABORATION) {
			return Messages.ModelUtil_Collaboration_Diagram;
		}
		else if (type == Bpmn2DiagramType.PROCESS) {
			return Messages.ModelUtil_Process_Diagram;
		}
		return Messages.ModelUtil_Unknown_Diagram_Type;
	}
	
	public static List<EStructuralFeature> getAnyAttributes(EObject object) {
		List<EStructuralFeature> list = new ArrayList<EStructuralFeature>();
		EStructuralFeature anyAttribute = ((EObject)object).eClass().getEStructuralFeature("anyAttribute"); //$NON-NLS-1$
		if (anyAttribute!=null && object.eGet(anyAttribute) instanceof BasicFeatureMap) {
			BasicFeatureMap map = (BasicFeatureMap)object.eGet(anyAttribute);
			for (Entry entry : map) {
				EStructuralFeature feature = entry.getEStructuralFeature();
				list.add(feature);
			}
		}
		return list;
	}
	
	public static EStructuralFeature getAnyAttribute(EObject object, String name) {
		EStructuralFeature anyAttribute = ((EObject)object).eClass().getEStructuralFeature("anyAttribute"); //$NON-NLS-1$
		if (anyAttribute!=null && object.eGet(anyAttribute) instanceof BasicFeatureMap) {
			BasicFeatureMap map = (BasicFeatureMap)object.eGet(anyAttribute);
			for (Entry entry : map) {
				EStructuralFeature feature = entry.getEStructuralFeature();
				if (feature.getName().equals(name))
					return feature;
			}
		}
		return null;
	}
	
	/**
	 * Removed "deprecated" annotation: ModelExtensionDescriptor.populateObject() needs this  
	 */
	public static EStructuralFeature addAnyAttribute(EObject childObject, String name, String type, Object value) {
		EPackage pkg = childObject.eClass().getEPackage();
		String nsURI = pkg.getNsURI();
		return addAnyAttribute(childObject, nsURI, name, type, value);
	}
	
	/**
	 * Removed "deprecated" annotation: ModelExtensionDescriptor.populateObject() needs this  
	 */
	@SuppressWarnings("unchecked")
	public static EStructuralFeature addAnyAttribute(EObject childObject, String namespace, String name, String type, Object value) {
		EStructuralFeature attr = null;
		EClass eclass = null;
		if (childObject instanceof EClass) {
			eclass = (EClass)childObject;
			childObject = ExtendedPropertiesAdapter.getDummyObject(eclass);
		}
		else
			eclass = childObject.eClass();
		EStructuralFeature anyAttribute = eclass.getEStructuralFeature(Bpmn2Package.BASE_ELEMENT__ANY_ATTRIBUTE);
		List<BasicFeatureMap.Entry> anyMap = (List<BasicFeatureMap.Entry>)childObject.eGet(anyAttribute);
		if (anyMap==null)
			return null;
		for (BasicFeatureMap.Entry fe : anyMap) {
			if (fe.getEStructuralFeature() instanceof EAttributeImpl) {
				EAttributeImpl a = (EAttributeImpl) fe.getEStructuralFeature();
				if (namespace.equals(a.getExtendedMetaData().getNamespace()) && name.equals(a.getName())) {
					attr = a;
					break;
				}
			}
		}
		
		// this featuremap can only hold attributes, not elements
		if (type==null)
			type = "E" + value.getClass().getSimpleName(); //$NON-NLS-1$
		EDataType eDataType = (EDataType)ModelUtil.getEClassifierFromString(null, type);//(EDataType)EcorePackage.eINSTANCE.getEClassifier(type);
		if (eDataType!=null) {
			if (attr==null) {
				attr = ExtendedMetaData.INSTANCE.demandFeature(namespace, name, false);
				attr.setEType(eDataType);
				anyMap.add( FeatureMapUtil.createEntry(attr, value) );
			}
			else {
				EClassifier dt = attr.getEType();
				if (dt==null || !eDataType.getInstanceClass().isAssignableFrom(dt.getInstanceClass()))
					throw new IllegalArgumentException(
						NLS.bind(
							Messages.ModelUtil_Illegal_Value,
							new Object[] {
								childObject.eClass().getName(),
								attr.getName(),
								attr.getEType().getName(),
								value.toString()
							}
						)
					);
				anyMap.add( FeatureMapUtil.createEntry(attr, value) );
			}
		}
		else if (attr==null) {
			attr = ExtendedMetaData.INSTANCE.demandFeature(namespace, name, false);
			anyMap.add( FeatureMapUtil.createEntry(attr, value) );
		}
		else {
			anyMap.add( FeatureMapUtil.createEntry(attr, value) );
		}
		return attr;
	}

	public static boolean isBpmnPackage(EPackage pkg) {
		return pkg == Bpmn2Package.eINSTANCE || pkg == BpmnDiPackage.eINSTANCE || pkg == DcPackage.eINSTANCE || pkg == DiPackage.eINSTANCE;
	}
	
	public static EAttribute createDynamicAttribute(EPackage pkg, EObject object, String name, String type) {
		if (isBpmnPackage(pkg)) {
			String namespace = TargetRuntime.getDefaultRuntime().getRuntimeExtension().getTargetNamespace(Bpmn2DiagramType.NONE);
			EStructuralFeature feature = ModelUtil.addAnyAttribute(object, namespace, name, type, null);
			if (feature instanceof EAttribute)
				return (EAttribute) feature;
			throw new IllegalArgumentException(NLS.bind(Messages.ModelUtil_Illegal_EPackage_For_Attribute, pkg.getName()));
		}
		EClass eClass = object instanceof EClass ? (EClass)object : object.eClass(); 
		EAttribute attr = null;
		EClass docRoot = (EClass)pkg.getEClassifier("DocumentRoot"); //$NON-NLS-1$
		if (docRoot==null) {
			ExtendedMetaData.INSTANCE.demandPackage(pkg.getNsURI());
			docRoot = ExtendedMetaData.INSTANCE.getDocumentRoot(pkg);
		}
		if (docRoot!=null) {
			for (EStructuralFeature f : docRoot.getEStructuralFeatures()) {
				if (f.getName().equals(name)) {
					if (f instanceof EAttribute) {
						attr = (EAttribute)f;
						break;
					}
					return null;
				}
			}
		}
		
		if (type==null)
			type = "EString"; //$NON-NLS-1$
		
		EClassifier eClassifier = null;
		if (type!=null) {
			eClassifier = getEClassifierFromString(pkg,type);
			if (eClassifier==null || !(eClassifier instanceof EDataType)) {
				String message =
					NLS.bind(
						Messages.ModelUtil_Unknown_Attribute_Data_Type,
						new Object[] {
							name,
							eClass.getName(),
							type
						}
					);
	
				MessageDialog.openError(Display.getDefault().getActiveShell(),
						Messages.ModelUtil_Internal_Error,
						message);
				throw new IllegalArgumentException(message);
			}
		}
		if (attr==null) {
			attr = EcorePackage.eINSTANCE.getEcoreFactory().createEAttribute();
			attr.setName(name);
			attr.setEType(eClassifier);
			ExtendedMetaData.INSTANCE.setFeatureKind(attr,ExtendedMetaData.ATTRIBUTE_FEATURE);
			
			docRoot.getEStructuralFeatures().add(attr);
			ExtendedMetaData.INSTANCE.setNamespace(attr, pkg.getNsURI());
			ExtendedMetaData.INSTANCE.setDocumentRoot(docRoot);
		}
		else if (eClassifier!=null)
			attr.setEType(eClassifier);
		
		// force this feature to be serialized regardless of whether its value is the default value
		attr.setUnsettable(true);
		
		return attr;
	}
	
	public static EReference createDynamicReference(EPackage pkg, EObject object, String name, String type) {
		if (isBpmnPackage(pkg)) {
			throw new IllegalArgumentException(NLS.bind(Messages.ModelUtil_Illegal_EPackage_For_Reference,pkg.getName()));
		}
		EClass eClass = object instanceof EClass ? (EClass)object : object.eClass(); 
		EReference ref = null;
		EClass docRoot = ExtendedMetaData.INSTANCE.getDocumentRoot(pkg);
		if (docRoot==null) {
			ExtendedMetaData.INSTANCE.demandPackage(pkg.getNsURI());
			docRoot = ExtendedMetaData.INSTANCE.getDocumentRoot(pkg);
			if (docRoot==null) {
				EClassifier e = pkg.getEClassifier("DocumentRoot"); //$NON-NLS-1$
				if (e instanceof EClass) {
					docRoot = (EClass)e;
				}
			}
		}
		if (docRoot!=null) {
			for (EStructuralFeature f : docRoot.getEStructuralFeatures()) {
				if (f.getName().equals(name)) {
					if (f instanceof EReference) {
						ref = (EReference)f;
						break;
					}
					return null;
				}
			}
		}

		EClassifier eClassifier = null;
		if (type!=null) {
			eClassifier = getEClassifierFromString(pkg,type);
			if (eClassifier==null || !(eClassifier instanceof EClass)) {
				String message =
					NLS.bind(
						Messages.ModelUtil_Unknown_Reference_Object_Type,
						new Object[] {
							name,
							eClass.getName(),
							type
						}
					);
	
				MessageDialog.openError(Display.getDefault().getActiveShell(),
						Messages.ModelUtil_Internal_Error,
						message);
				throw new IllegalArgumentException(message);
			}
		}
		if (ref==null) {
			ref = EcorePackage.eINSTANCE.getEcoreFactory().createEReference();
			ref.setName(name);
			ref.setEType(eClassifier);
			ExtendedMetaData.INSTANCE.setFeatureKind(ref,ExtendedMetaData.ATTRIBUTE_FEATURE);
			
			docRoot.getEStructuralFeatures().add(ref);
			ExtendedMetaData.INSTANCE.setNamespace(ref, pkg.getNsURI());
			ExtendedMetaData.INSTANCE.setDocumentRoot(docRoot);
		}
		else if (eClassifier!=null)
			ref.setEType(eClassifier);
		
		return ref;
	}
	
	public static boolean removeDynamicFeature(EPackage pkg, EObject object, String name) {
		if (isBpmnPackage(pkg)) {
			throw new IllegalArgumentException("Can not remove dynamic feature from "+pkg.getName()); //$NON-NLS-1$
		}
		
		EStructuralFeature anyAttribute = ((EObject)object).eClass().getEStructuralFeature("anyAttribute"); //$NON-NLS-1$
		if (anyAttribute!=null && object.eGet(anyAttribute) instanceof BasicFeatureMap) {
			BasicFeatureMap map = (BasicFeatureMap)object.eGet(anyAttribute);
			for (Entry entry : map) {
				EStructuralFeature feature = entry.getEStructuralFeature();
				if (feature.getName().equals(name)) {
					map.remove(entry);
					return true;
				}
			}
		}
		
		return false;
	}
	
	public static EClassifier getEClassifierFromString(EPackage pkg, String type) {
		EClassifier eClassifier = null;
		if (type==null) {
			return EcorePackage.eINSTANCE.getEObject();
		}
		if (pkg!=null) {
			eClassifier = pkg.getEClassifier(type);
			if (eClassifier!=null)
				return eClassifier;
		}
		
		eClassifier = EcorePackage.eINSTANCE.getEClassifier(type);
		if (eClassifier!=null)
			return eClassifier;
		
		eClassifier = Bpmn2Package.eINSTANCE.getEClassifier(type);
		if (eClassifier!=null)
			return eClassifier;
		
		eClassifier = BpmnDiPackage.eINSTANCE.getEClassifier(type);
		if (eClassifier!=null)
			return eClassifier;
		
		return null;
	}
	
	public static EObject createStringWrapper(String value) {
		DynamicEObjectImpl de = new DynamicEObjectImpl() {
			// prevent owners from trying to resolve this thing - it's just a string!
			public boolean eIsProxy() {
				return false;
			}

			@Override
			public boolean equals(Object object) {
				if (object instanceof DynamicEObjectImpl) {
					DynamicEObjectImpl that = (DynamicEObjectImpl) object;
					if (eProxyURI()==null) {
						return that.eProxyURI()==null;
					}
					String thisString = eProxyURI().toString();
					String thatString = that.eProxyURI() == null ? null : that.eProxyURI().toString();
					return thisString.equals(thatString);
				}
				else if (object instanceof String) {
					String thisString = eProxyURI().toString();
					return thisString.equals(object);
				}
				return super.equals(object);
			}
			
		};
		de.eSetClass(EcorePackage.eINSTANCE.getEObject());
		de.eSetProxyURI(URI.createURI(value));
		return de;
	}
	
	public static String getStringWrapperValue(Object wrapper) {
		if (wrapper instanceof DynamicEObjectImpl) {
			DynamicEObjectImpl de = (DynamicEObjectImpl)wrapper;
			URI uri = de.eProxyURI();
			return uri.toString();
		}
		else if (wrapper instanceof EObject) {
			return EcoreUtil.getURI((EObject)wrapper).toString();
		}
		return null;
	}
	
	public static boolean setStringWrapperValue(Object wrapper, String value) {
		if (isStringWrapper(wrapper)) {
			DynamicEObjectImpl de = (DynamicEObjectImpl)wrapper;
			de.eSetProxyURI(URI.createURI(value));
			return true;
		}
		return false;
	}
	
	public static boolean isStringWrapper(Object wrapper) {
		return wrapper instanceof DynamicEObjectImpl;
	}
	
	public static boolean isElementSelected(IDiagramContainer editor, PictogramElement element) {
		for (PictogramElement search : editor.getSelectedPictogramElements()) {
			if (search.equals(element)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Given an EObject always returns the BPMN2 Resource that is associated with that object.
	 * This may involve searching for all Resources in the ResourceSet that the EObject belongs to.
	 * This also searches for a Resource in the object's InsertionAdapter if the object is not yet
	 * contained in any Resource.
	 * 
	 * @param object
	 * @return
	 */
	public static Resource getResource(EObject object) {
		Resource resource = null;
		if (object!=null) {
			resource = object.eResource();
			if (resource!=null) {
				ResourceSet rs = resource.getResourceSet();
				if (rs!=null) {
					for (Resource r : rs.getResources()) {
						if (r instanceof Bpmn2Resource) {
							return r;
						}
					}
				}
			}
			if (resource==null) {
				InsertionAdapter insertionAdapter = AdapterUtil.adapt(object, InsertionAdapter.class);
				if (insertionAdapter!=null)
					resource = insertionAdapter.getResource();
				// TODO: can we use any of the referenced objects to find a Resource?
			}
		}
		return resource;
	}

	public static Resource getResource(DiagramEditor editor) {
		if (editor!=null)
			return getResource(editor.getDiagramTypeProvider().getDiagram());
		return null;
	}
	
	public static EObject getContainer(EObject object) {
		EObject container = null;
		if (object!=null) {
			container = object.eContainer();
			if (container==null) {
				InsertionAdapter insertionAdapter = AdapterUtil.adapt(object, InsertionAdapter.class);
				if (insertionAdapter!=null)
					container = insertionAdapter.getObject();
			}
		}
		return container;
	}

	public static Definitions getDefinitions(EObject object) {
		Resource resource = getResource(object);
		return getDefinitions(resource);
	}
	
	public static Definitions getDefinitions(Resource resource) {
		if (resource!=null && !resource.getContents().isEmpty() && !resource.getContents().get(0).eContents().isEmpty()) {
			Object defs = resource.getContents().get(0).eContents().get(0);
			if (defs instanceof Definitions)
				return (Definitions)defs;
		}
		return null;
	}
	
	public static DocumentRoot getDocumentRoot(EObject object) {
		Resource resource = getResource(object);
		if (resource!=null) {
			EList<EObject> contents = resource.getContents();
			if (!contents.isEmpty() && contents.get(0) instanceof DocumentRoot)
				return (DocumentRoot)contents.get(0);
		}
		return null;
	}
	
	public static List<EObject> getAllReachableObjects(EObject object, EStructuralFeature feature) {
		ArrayList<EObject> list = null;
		if (object!=null && feature.getEType() instanceof EClass) {
			Resource resource = getResource(object);
			if (resource!=null) {
				EClass eClass = (EClass)feature.getEType();
				if (eClass != EcorePackage.eINSTANCE.getEObject()) {
					list = new ArrayList<EObject>();
					TreeIterator<EObject> contents = resource.getAllContents();
					while (contents.hasNext()) {
						Object item = contents.next();
						if (eClass.isInstance(item)) {
							list.add((EObject)item);
						}
					}
				}
			}
		}
		return list;
	}
	
	public static List<EObject> getAllReachableObjects(EObject object, EClass eClass) {
		ArrayList<EObject> list = null;
		Resource resource = getResource(object);
		if (resource!=null) {
			list = new ArrayList<EObject>();
			if (eClass != EcorePackage.eINSTANCE.getEObject()) {
				TreeIterator<EObject> contents = resource.getAllContents();
				while (contents.hasNext()) {
					Object item = contents.next();
					if (eClass.isInstance(item)) {
						list.add((EObject)item);
					}
				}
			}
		}
		return list;
	}

	@SuppressWarnings("unchecked")
	public static <T> List<T> getAllRootElements(Definitions definitions, final Class<T> class1) {
		ArrayList<T> list = new ArrayList<T>();
		if (definitions!=null) {
			for (RootElement re : definitions.getRootElements()) {
				if (class1.isInstance(re)) {
					list.add((T) re);
				}
			}
		}
		return list;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> List<T> getAllObjectsOfType(Resource resource, final Class<T> class1) {
		ArrayList<T> l = new ArrayList<T>();
		TreeIterator<EObject> iter = resource.getAllContents();
		while (iter.hasNext()) {
			Object t = iter.next();
			if (class1.isInstance(t)) {
				l.add((T) t);
			}
		}
		return l;
	}

	public static boolean compare(Object v1, Object v2) {
		if (v1==null) {
			if (v2!=null)
				return false;
		}
		else if (v2==null) {
			if (v1!=null)
				return false;
		}
		return v1.equals(v2);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static EObject findNearestAncestor(EObject object, Class[] types) {
		EObject ancestor = null;
		if (object!=null) {
			ancestor = getContainer(object);
			while (ancestor!=null) {
				Class type = ancestor.getClass();
				for (Class t : types) {
					if (t.isAssignableFrom(type))
						return ancestor;
				}
				ancestor = getContainer(ancestor);
			}
		}
		return ancestor;
	}
	
	@SuppressWarnings("rawtypes")
	public static List<EObject> collectAncestorObjects(EObject object, String featureName, Class[] ancestorTypes) {
		return collectAncestorObjects(object, featureName, ancestorTypes, null);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List<EObject> collectAncestorObjects(EObject object, String featureName, Class[] ancestorTypes, Class[] objectTypes) {
		List<EObject> values = new ArrayList<EObject>();
		EObject ancestor = ModelUtil.findNearestAncestor(object, ancestorTypes);
		while (ancestor!=null) {
			EStructuralFeature feature = ancestor.eClass().getEStructuralFeature(featureName);
			if (feature!=null && ancestor.eGet(feature) instanceof List) {
				List<EObject> objects = (List<EObject>) ancestor.eGet(feature);
				if (objectTypes==null) {
					values.addAll(objects);
				}
				else {
					for (EObject item : objects) {
						for (Class t : objectTypes) {
							if (t.isAssignableFrom(item.getClass()))
								values.add(item);
						}
					}
				}
			}
			ancestor = ModelUtil.findNearestAncestor(ancestor, ancestorTypes);
		}
		return values;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> List<T> getAllExtensionAttributeValues(EObject object, Class<T> clazz) {
		List<T> results = new ArrayList<T>();
		
		if (object!=null) {
			EStructuralFeature evf = object.eClass().getEStructuralFeature("extensionValues"); //$NON-NLS-1$
			EList<ExtensionAttributeValue> list = (EList<ExtensionAttributeValue>)object.eGet(evf);
			for (ExtensionAttributeValue eav : list) {
				FeatureMap fm = eav.getValue();
				for (Entry e : fm) {
					if (clazz.isInstance(e.getValue())) {
						results.add((T)e.getValue());
					}
				}
			}
		}
		return results;
	}
	
	public static List<ExtensionAttributeValue> getExtensionAttributeValues(EObject be) {
		if (be instanceof Participant) {
			final Participant participant = (Participant) be;
			if (participant.getProcessRef() == null) {
				if (participant.eContainer() instanceof Collaboration) {
					Collaboration collab = (Collaboration) participant.eContainer();
					if (collab.eContainer() instanceof Definitions) {
						final Definitions definitions = getDefinitions(collab);
						
						TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(definitions.eResource());
						
						domain.getCommandStack().execute(new RecordingCommand(domain) {
							@Override
							protected void doExecute() {
								Process process = Bpmn2ModelerFactory.create(Process.class);
								participant.setProcessRef(process);
								definitions.getRootElements().add(process);
								ModelUtil.setID(process);
							}
							
						});
						
					}
				}
			}
			return participant.getProcessRef().getExtensionValues();
		}
		if (be instanceof BPMNDiagram) {
			BPMNDiagram diagram = (BPMNDiagram) be;
			BaseElement bpmnElement = diagram.getPlane().getBpmnElement();
			if (bpmnElement instanceof org.eclipse.bpmn2.Process) {
				return bpmnElement.getExtensionValues();
			}
		}
		if (be instanceof BaseElement) {
			return ((BaseElement) be).getExtensionValues();
		}

		return new ArrayList<ExtensionAttributeValue>();
	}
	
	public static void addExtensionAttributeValue(EObject object, EStructuralFeature feature, Object value) {
		addExtensionAttributeValue(object, feature, value, false);
	}
	
	@SuppressWarnings("unchecked")
	public static void addExtensionAttributeValue(EObject object, EStructuralFeature feature, Object value, boolean delay) {
		EStructuralFeature evf = object.eClass().getEStructuralFeature("extensionValues"); //$NON-NLS-1$
		EList<EObject> list = (EList<EObject>)object.eGet(evf);
		
		if (list.size()==0) {
			ExtensionAttributeValue newItem = Bpmn2ModelerFactory.create(ExtensionAttributeValue.class);
			ModelUtil.setID(newItem);
			FeatureMap map = newItem.getValue();
			map.add(feature, value);
			if (delay) {
				InsertionAdapter.add(object, evf, newItem, feature, value);
			}
			else {
				list.add(newItem);
			}
		}
		else {
			ExtensionAttributeValue oldItem = (ExtensionAttributeValue) list.get(0);
			if (delay) {
				InsertionAdapter.add(object, evf, oldItem, feature, value);
			}
			else {
				FeatureMap map = oldItem.getValue();
				map.add(feature, value);
			}
		}
	}

	/*
	 * Various model object and feature UI property methods
	 */
	@SuppressWarnings("rawtypes")
	public static String getLabel(Object object) {
		String label = ""; //$NON-NLS-1$
		if (object instanceof EObject) {
			EObject eObject = (EObject)object;
			ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(eObject);
			if (adapter!=null)
				label = adapter.getObjectDescriptor().getLabel(eObject);
			else
				label = toDisplayName( eObject.eClass().getName() );
		}
		else
			label = object.toString();
		label = label.replaceAll(" Ref$", ""); //$NON-NLS-1$ //$NON-NLS-2$
		return label;
	}

	@SuppressWarnings("rawtypes")
	public static void setLabel(EObject object, EStructuralFeature feature, String label) {
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null)
			adapter.getFeatureDescriptor(feature).setLabel(label);
	}

	@SuppressWarnings("rawtypes")
	public static String getLabel(EObject object, EStructuralFeature feature) {
		String label = ""; //$NON-NLS-1$
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null)
			label = adapter.getFeatureDescriptor(feature).getLabel(object);
		else
			label = toDisplayName( feature.getName() );
		label = label.replaceAll(" Ref$", ""); //$NON-NLS-1$ //$NON-NLS-2$
		return label;
	}

	@SuppressWarnings("rawtypes")
	public static String getDisplayName(Object object) {
		if (object instanceof EObject) {
			EObject eObject = (EObject)object;
			ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(eObject);
			if (adapter!=null) {
				String text = adapter.getObjectDescriptor().getDisplayName(eObject);
				if (text!=null && !text.isEmpty()) {
					return text;
				}
			}
			return getLongDisplayName(eObject);
		}
		return object==null ? null : object.toString();
	}

	@SuppressWarnings("rawtypes")
	public static String getDisplayName(EObject object, EStructuralFeature feature) {
		if (feature==null)
			return getDisplayName(object);
		
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null)
			return adapter.getFeatureDescriptor(feature).getDisplayName(object);
		return getLongDisplayName(object, feature);
	}

	@SuppressWarnings("rawtypes")
	public static boolean setMultiLine(EObject object, EStructuralFeature feature, boolean multiLine) {
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null) {
			adapter.getFeatureDescriptor(feature).setMultiLine(multiLine);
			return true;
		}
		return false;
	}

	@SuppressWarnings("rawtypes")
	public static boolean isMultiLine(EObject object, EStructuralFeature feature) {
		if (feature==null)
			return false;
		
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null)
			return adapter.getFeatureDescriptor(feature).isMultiLine(object);
		return false;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Hashtable<String, Object> getChoiceOfValues(EObject object, EStructuralFeature feature) {
		if (feature==null)
			return null;
		
		if (feature.getEType() instanceof EEnum) {
			EEnum en = (EEnum)feature.getEType();
			Hashtable<String,Object> choices = new Hashtable<String,Object>();
			for (EEnumLiteral el : en.getELiterals()) {
				choices.put(el.getLiteral(), el.getInstance());
			}
			return choices;
		}
		
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null)
			return adapter.getFeatureDescriptor(feature).getChoiceOfValues(object);
		return null;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static boolean setValue(TransactionalEditingDomain domain, final EObject object, final EStructuralFeature feature, Object value) {
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);

		try {
			InsertionAdapter.executeIfNeeded(object);
			if (value instanceof EObject) {
				// make sure the new object is added to its control first
				// so that it inherits the control's Resource and EditingDomain
				// before we try to change its value.
				InsertionAdapter.executeIfNeeded((EObject)value);
			}
			if (value instanceof String && ((String) value).isEmpty()) {
				if (!(feature.getDefaultValue() instanceof String))
					value = null;
			}
			
			if (adapter!=null) {
				if (!adapter.getFeatureDescriptor(feature).equals(value)) {
					adapter.getFeatureDescriptor(feature).setValue(value);
				}
			}
			else if (domain!=null) {
				final Object v = value;
				domain.getCommandStack().execute(new RecordingCommand(domain) {
					@Override
					protected void doExecute() {
						if (object.eGet(feature) instanceof List) {
							((List)object.eGet(feature)).add(v);
						}
						else
							object.eSet(feature, v);
					}
				});
			}
			else {
				if (object.eGet(feature) instanceof List) {
					((List)object.eGet(feature)).add(value);
				}
				else
					object.eSet(feature, value);
			}
		} catch (Exception e) {
			ErrorUtils.showErrorMessage(e.getMessage());
			return false;
		}
		return true;
	}

	@SuppressWarnings("rawtypes")
	public static Object getValue(final EObject object, final EStructuralFeature feature) {
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		Object value = adapter==null ? object.eGet(feature) : adapter.getFeatureDescriptor(feature).getValue();
		return value;
	}

	public static boolean compare(EObject object1, EObject object2, boolean similar) {
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object1, null);
		if (adapter!=null)
			return adapter.getObjectDescriptor().compare(object1, object2, similar);
		return object1.equals(object2);
	}
	
	@SuppressWarnings("rawtypes")
	public static boolean canEdit(EObject object, EStructuralFeature feature) {
		if (feature!=null && feature.getEType() instanceof EClass) {
			ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
			if (adapter!=null) {
				Object result = adapter.getProperty(feature, ExtendedPropertiesAdapter.UI_CAN_EDIT);
				if (result instanceof Boolean)
					return ((Boolean)result);
			}
			if (feature instanceof EReference) {
				if (((EReference)feature).isContainment())
					return true;
				if (Bpmn2Package.eINSTANCE.getRootElement().isSuperTypeOf((EClass)feature.getEType()))
					return true;
				if (feature.isMany())
					return true;
				return false;
			}
			return true;
		}
		return false;
	}

	@SuppressWarnings("rawtypes")
	public static boolean canCreateNew(EObject object, EStructuralFeature feature) {
		if (feature!=null && feature.getEType() instanceof EClass) {
			ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
			if (adapter!=null) {
				Object result = adapter.getProperty(feature, ExtendedPropertiesAdapter.UI_CAN_CREATE_NEW);
				if (result instanceof Boolean)
					return ((Boolean)result);
			}
			if (feature instanceof EReference) {
				if (((EReference)feature).isContainment())
					return true;
				if (Bpmn2Package.eINSTANCE.getRootElement().isSuperTypeOf((EClass)feature.getEType()))
					return true;
				return false;
			}
			return true;
		}
		return false;
	}

	@SuppressWarnings("rawtypes")
	public static boolean canEditInline(EObject object, EStructuralFeature feature) {
		if (feature!=null && feature.getEType() instanceof EClass) {
			ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
			if (adapter!=null) {
				Object result = adapter.getProperty(feature, ExtendedPropertiesAdapter.UI_CAN_EDIT_INLINE);
				if (result instanceof Boolean)
					return ((Boolean)result);
			}
		}
		return false;
	}

	@SuppressWarnings("rawtypes")
	public static boolean canSetNull(EObject object, EStructuralFeature feature) {
		if (feature!=null && feature.getEType() instanceof EClass) {
			ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
			if (adapter!=null) {
				Object result = adapter.getProperty(feature, ExtendedPropertiesAdapter.UI_CAN_SET_NULL);
				if (result instanceof Boolean)
					return ((Boolean)result);
			}
			return true;
		}
		return false;
	}

	@SuppressWarnings("rawtypes")
	public static boolean isMultiChoice(EObject object, EStructuralFeature feature) {
		if (feature==null) {
			return false;
		}
		if (feature.getEType() instanceof EEnum) {
			return true;
		}
		
		ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(object, feature);
		if (adapter!=null) {
			Object result = adapter.getProperty(feature, ExtendedPropertiesAdapter.UI_IS_MULTI_CHOICE);
			if (result instanceof Boolean)
				return ((Boolean)result);
		}

		return getChoiceOfValues(object,feature) != null;
	}

	/*
	 * Fallbacks in case a property provider does not exist
	 */
	public static String getLongDisplayName(EObject object) {
		String objName = null;
		if (object instanceof BPMNDiagram) {
			Bpmn2DiagramType type = getDiagramType((BPMNDiagram)object); 
			if (type == Bpmn2DiagramType.CHOREOGRAPHY) {
				objName = Messages.ModelUtil_Choreography_Diagram;
			}
			else if (type == Bpmn2DiagramType.COLLABORATION) {
				objName = Messages.ModelUtil_Collaboration_Diagram;
			}
			else if (type == Bpmn2DiagramType.PROCESS) {
				objName = Messages.ModelUtil_Process_Diagram;
			}
		}
		if (objName==null){
			objName = toDisplayName( object.eClass().getName() );
		}
		EStructuralFeature feature = object.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
		if (feature!=null) {
			String name = (String)object.eGet(feature);
			if (name==null || name.isEmpty())
				name = NLS.bind(Messages.ModelUtil_Unnamed_Object, objName);
			else
				name = objName + " \"" + name + "\""; //$NON-NLS-1$ //$NON-NLS-2$
			return name;
		}
		feature = object.eClass().getEStructuralFeature("id"); //$NON-NLS-1$
		if (feature!=null) {
			String id = (String)object.eGet(feature);
			if (id==null || id.isEmpty())
				id = Messages.ModelUtil_Unknown_Object + objName;
			else
				id = objName + " \"" + id + "\""; //$NON-NLS-1$ //$NON-NLS-2$
			return id;
		}
		feature = object.eClass().getEStructuralFeature("qName"); //$NON-NLS-1$
		if (feature!=null) {
			Object qName = object.eGet(feature);
			if (qName!=null) {
				return qName.toString();
			}
		}
		return objName;
	}

	public static String getLongDisplayName(EObject object, EStructuralFeature feature) {
		Object value = object.eGet(feature);
		if (value==null)
			return ""; //$NON-NLS-1$
		return value.toString();
	}

	public static boolean isEmpty(Object result) {
		if (result == null)
			return true;
		if (result instanceof String)
			return ((String) result).isEmpty();
		return false;
	}

	public static void disposeChildWidgets(Composite parent) {
		int i = 0;
		Control[] kids = parent.getChildren();
		for (Control k : kids) {
			if (k instanceof Composite) {
				disposeChildWidgets((Composite)k);
			}
			k.dispose();
			++i;
		}
		kids = parent.getChildren();
	}

	/**
	 * Ugly hack to force layout of the entire widget tree of the property sheet page.
	 * @param parent
	 */
	public static void recursivelayout(Composite parent) {
		Control[] kids = parent.getChildren();
		for (Control k : kids) {
			if (k.isDisposed())
				Activator.logError(new SWTException("Widget is disposed.")); //$NON-NLS-1$
			if (k instanceof Composite) {
				recursivelayout((Composite)k);
				((Composite)k).layout(true);
			}
		}
		parent.layout(true);
	}

	public static DiagramEditor getEditor(EObject object) {
		Resource resource = InsertionAdapter.getResource(object);
		if(resource!=null)
			return getEditor(resource.getResourceSet());
		return null;
	}

	public static DiagramEditor getEditor(Resource resource) {
		if(resource!=null)
			return getEditor(resource.getResourceSet());
		return null;
	}
	
	public static DiagramEditor getEditor(ResourceSet resourceSet) {
	    Iterator<Adapter> it = resourceSet.eAdapters().iterator();
	    while (it.hasNext()) {
	        Object next = it.next();
	        if (next instanceof DiagramEditorAdapter) {
	            return ((DiagramEditorAdapter)next).getDiagramEditor();
	        }
	    }
	    return null;
	}

	public static EPackage getEPackage(EStructuralFeature feature) {
		EObject o = feature;
		while ( o.eContainer()!=null ) {
			o = o.eContainer();
			if (o instanceof EPackage) {
				return (EPackage)o;
			}
		}
		return null;
	}
	
	/**
	 * This is a workaround to deal with FormalExpressions: if the "body" of an expression
	 * is null, the default FormalExpression.getBody() method returns the string "null"
	 * which is not exactly what we want! We need to know if the body is actually null,
	 * or if it contains the string "null".
	 * 
	 * @param expression
	 * @return
	 */
	public static String getExpressionBody(FormalExpression expression) {
		String body = null;
        if (expression.getMixed() != null && !expression.getMixed().isEmpty()) {
            StringBuilder result = new StringBuilder();
            boolean isNull = true;
            for (FeatureMap.Entry cur : expression.getMixed()) {
                switch (cur.getEStructuralFeature().getFeatureID()) {
                case XMLTypePackage.XML_TYPE_DOCUMENT_ROOT__CDATA:
                case XMLTypePackage.XML_TYPE_DOCUMENT_ROOT__TEXT:
                	if (cur.getValue()!=null) {
                		isNull = false;
                		result.append(cur.getValue());
                	}
                    break;

                default:
                    break;
                }
            }
            if (!isNull)
            	body = result.toString();
        }
        return body;
    }

	public static List<Tuple<EObject,EObject>> findDuplicateIds(Resource resource) {
		List<Tuple<EObject,EObject>> list = new ArrayList<Tuple<EObject,EObject>>();
		Definitions definitions = ModelUtil.getDefinitions(resource);
		TreeIterator<EObject> iter1 = definitions.eAllContents();
		HashSet<EObject> map = new HashSet<EObject>();
		while (iter1.hasNext()) {
			EObject o1 = iter1.next();
			EStructuralFeature id1Feature = o1.eClass().getEIDAttribute();
			if (id1Feature!=null && !map.contains(o1)) {
				TreeIterator<EObject> iter2 = definitions.eAllContents();
				map.add(o1);
				String id1 = (String)o1.eGet(id1Feature);
				
				while (iter2.hasNext()) {
					EObject o2 = iter2.next();
					EStructuralFeature id2Feature = o2.eClass().getEIDAttribute();
					if (id2Feature!=null && o1!=o2 && !map.contains(o2)) {
						String id2 = (String)o2.eGet(id2Feature);
						if (id1!=null && !id1.isEmpty() && id2!=null && !id2.isEmpty()) {
							if (id1.equals(id2)) {
								list.add( new Tuple<EObject,EObject>(o1,o2) );
							}
						}
					}
				}
			}
		}
		
		return list;
	}
	
	public static boolean isParticipantBand(Participant participant) {
		Resource resource = ModelUtil.getResource(participant);
		for (ChoreographyActivity ca : ModelUtil.getAllObjectsOfType(resource, ChoreographyActivity.class)) {
			if (ca.getParticipantRefs().contains(participant)) {
				return true;
			}
		}
		return false;
	}
}
