https://bugs.eclipse.org/bugs/show_bug.cgi?id=488889
MultInstanceLoopCharacteristics input and output data objects are not
handled properly for Tasks
diff --git a/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/ProcessVariableNameChangeAdapter.java b/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/ProcessVariableNameChangeAdapter.java
index 83de9e4..2e87372 100644
--- a/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/ProcessVariableNameChangeAdapter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/ProcessVariableNameChangeAdapter.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.bpmn2.DataInput;
 import org.eclipse.bpmn2.DataObject;
+import org.eclipse.bpmn2.DataOutput;
 import org.eclipse.bpmn2.Error;
 import org.eclipse.bpmn2.Escalation;
 import org.eclipse.bpmn2.Message;
@@ -68,12 +69,12 @@
 				object instanceof Error ||
 				object instanceof Escalation ||
 				object instanceof GlobalType ||
-				(
-						// DataInput objects are a special case: Only keep the name and
-						// ID in sync if the DataInput is being used as the instance
-						// parameter for MultiInstanceLoopCharacteristics (or if the
-						// DataInput hasn't been added to a container yet).
-						object instanceof DataInput && (
+					(
+						// DataInput and DataOutput objects are a special case: Only
+						// keep the name and ID in sync if the DataInput is being used
+						// as the instance parameter for MultiInstanceLoopCharacteristics
+						// (or if the object hasn't been added to a container yet).
+						(object instanceof DataInput || object instanceof DataOutput) && (
 						object.eContainer() instanceof MultiInstanceLoopCharacteristics ||
 						object.eContainer()==null)
 					)
diff --git a/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/property/adapters/JbpmMultiInstanceLoopCharacteristicsPropertiesAdapter.java b/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/property/adapters/JbpmMultiInstanceLoopCharacteristicsPropertiesAdapter.java
index 16f722d..03eeded 100644
--- a/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/property/adapters/JbpmMultiInstanceLoopCharacteristicsPropertiesAdapter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.runtime.jboss.jbpm/src/org/eclipse/bpmn2/modeler/runtime/jboss/jbpm5/property/adapters/JbpmMultiInstanceLoopCharacteristicsPropertiesAdapter.java
@@ -10,266 +10,69 @@
  ******************************************************************************/
 package org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.property.adapters;
 
+import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 
-import org.eclipse.bpmn2.Bpmn2Package;
-import org.eclipse.bpmn2.DataInput;
-import org.eclipse.bpmn2.DataInputAssociation;
-import org.eclipse.bpmn2.DataOutput;
-import org.eclipse.bpmn2.DataOutputAssociation;
-import org.eclipse.bpmn2.InputOutputSpecification;
-import org.eclipse.bpmn2.InputSet;
-import org.eclipse.bpmn2.ItemAwareElement;
 import org.eclipse.bpmn2.MultiInstanceLoopCharacteristics;
-import org.eclipse.bpmn2.OutputSet;
 import org.eclipse.bpmn2.Process;
-import org.eclipse.bpmn2.SubProcess;
+import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter;
 import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.JavaVariableNameObjectEditor;
-import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
-import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
+import org.eclipse.bpmn2.modeler.core.model.ModelDecorator;
+import org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.model.drools.GlobalType;
 import org.eclipse.bpmn2.modeler.ui.adapters.properties.MultiInstanceLoopCharacteristicsPropertiesAdapter;
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.resource.Resource;
 
 public class JbpmMultiInstanceLoopCharacteristicsPropertiesAdapter extends MultiInstanceLoopCharacteristicsPropertiesAdapter {
 
 	public JbpmMultiInstanceLoopCharacteristicsPropertiesAdapter(AdapterFactory adapterFactory, MultiInstanceLoopCharacteristics object) {
 		super(adapterFactory, object);
 
-		EStructuralFeature feature = Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_InputDataItem();
-		setProperty(feature, UI_OBJECT_EDITOR_CLASS, JavaVariableNameObjectEditor.class);
-		
-		feature = Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_OutputDataItem();
-		setProperty(feature, UI_OBJECT_EDITOR_CLASS, JavaVariableNameObjectEditor.class);
+		setProperty(INPUT_DATA_ITEM, UI_OBJECT_EDITOR_CLASS, JavaVariableNameObjectEditor.class);
+		setProperty(OUTPUT_DATA_ITEM, UI_OBJECT_EDITOR_CLASS, JavaVariableNameObjectEditor.class);
 
-		setFeatureDescriptor(LOOP_DATA_INPUT_REF, new LoopCharacteristicsDataIoFeatureDescriptor(this, object, LOOP_DATA_INPUT_REF) {
+		setFeatureDescriptor(LOOP_DATA_INPUT_REF, new LoopDataInputCollectionFeatureDescriptor(this, object) {
 			@Override
 			public Hashtable<String, Object> getChoiceOfValues() {
-				Hashtable<String, Object> choices = new Hashtable<String, Object>();
-				EObject container = ModelUtil.getContainer(object);
-				if (container instanceof SubProcess) {
-					// get the Property instances (a.k.a. "local variables") of the containing Process or SubProcess
-					for (EObject p : ModelUtil.collectAncestorObjects(object, "properties", new Class[] {Process.class, SubProcess.class})) { 
-						choices.put( getChoiceString(p), p);
-					}
+				Hashtable<String, Object> choices = super.getChoiceOfValues();
+				for (GlobalType g : getAllGlobals(object)) {
+					ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(g);
+					choices.put(adapter.getObjectDescriptor().getTextValue(), g);
 				}
 				return choices;
 			}
-			
-			@Override
-			protected void internalSet(MultiInstanceLoopCharacteristics object, EStructuralFeature feature, Object value, int index) {
-				if (object.eContainer() instanceof SubProcess) {
-					SubProcess subprocess = (SubProcess) object.eContainer();
-					InputOutputSpecification ioSpec = subprocess.getIoSpecification();
-					Resource resource = getResource();
-					if (value instanceof ItemAwareElement) {
-						ItemAwareElement element = (ItemAwareElement) value;
-						DataInput input = null;
-						InputSet inputSet = null;
-						DataInputAssociation inputAssociation = null;
-						if (ioSpec==null) {
-							ioSpec = Bpmn2ModelerFactory.create(resource, InputOutputSpecification.class);
-							subprocess.setIoSpecification(ioSpec);
-						}
-						else {
-							for (DataInput din : ioSpec.getDataInputs()) {
-								if (din == object.getLoopDataInputRef()) {
-									input = din;
-									break;
-								}
-							}
-						}
-						if (input == null)
-							input = Bpmn2ModelerFactory.create(resource, DataInput.class);
-						input.setName(element.getId());
-						input.setItemSubjectRef(element.getItemSubjectRef());
-						input.setIsCollection(true);
-						if (!ioSpec.getDataInputs().contains(input))
-							ioSpec.getDataInputs().add(input);
-						
-						for (InputSet is : ioSpec.getInputSets()) {
-							if (is.getDataInputRefs().contains(input)) {
-								inputSet = is;
-								break;
-							}
-						}
-						if (inputSet == null) {
-							if (ioSpec.getInputSets().size()==0) {
-								inputSet = Bpmn2ModelerFactory.create(resource, InputSet.class);
-								ioSpec.getInputSets().add(inputSet);
-							}
-							else
-								inputSet = ioSpec.getInputSets().get(0);
-						}
-						if (!inputSet.getDataInputRefs().contains(input))
-							inputSet.getDataInputRefs().add(input);
-
-						for (DataInputAssociation dia : subprocess.getDataInputAssociations()) {
-							if (dia.getTargetRef()==input) {
-								inputAssociation = dia;
-								break;
-							}
-						}
-						if (inputAssociation == null) {
-							inputAssociation = Bpmn2ModelerFactory.create(resource, DataInputAssociation.class);
-							subprocess.getDataInputAssociations().add(inputAssociation);
-						}
-						
-						inputAssociation.setTargetRef(input);
-						inputAssociation.getSourceRef().clear();
-						inputAssociation.getSourceRef().add(element);
-						
-						value = input;
-					}
-					else if (value==null) {
-						ItemAwareElement input = object.getLoopDataInputRef();
-						if (ioSpec!=null) {
-							if (input!=null) {
-								for (DataInput din : ioSpec.getDataInputs()) {
-									if (din == input) {
-										ioSpec.getDataInputs().remove(din);
-										if (ioSpec.getInputSets().size()>0) {
-											ioSpec.getInputSets().get(0).getDataInputRefs().remove(din);
-											if (ioSpec.getInputSets().get(0).getDataInputRefs().size()==0)
-												ioSpec.getInputSets().remove(0);
-										}
-										break;
-									}
-								}
-								int i = 0;
-								for (DataInputAssociation dia : subprocess.getDataInputAssociations()) {
-									if (dia.getTargetRef() == input) {
-										subprocess.getDataInputAssociations().remove(i);
-										break;
-									}
-									++i;
-								}
-							}
-							if (ioSpec.getDataInputs().size()==0 && ioSpec.getDataOutputs().size()==0) {
-								subprocess.setIoSpecification(null);
-							}
-						}
-					}
-				}
-				super.internalSet(object, feature, value, index);
-			}
 		});
 		
-		setFeatureDescriptor(LOOP_DATA_OUTPUT_REF, new LoopCharacteristicsDataIoFeatureDescriptor(this, object, LOOP_DATA_OUTPUT_REF) {
+		setFeatureDescriptor(LOOP_DATA_OUTPUT_REF, new LoopDataOutputCollectionFeatureDescriptor(this, object) {
 			@Override
 			public Hashtable<String, Object> getChoiceOfValues() {
-				Hashtable<String, Object> choices = new Hashtable<String, Object>();
-				EObject container = ModelUtil.getContainer(object);
-				if (container instanceof SubProcess) {
-					// get the Property instances (a.k.a. "local variables") of the containing Process or SubProcess
-					for (EObject p : ModelUtil.collectAncestorObjects(object, "properties", new Class[] {Process.class, SubProcess.class})) { 
-						choices.put( getChoiceString(p), p);
-					}
+				Hashtable<String, Object> choices = super.getChoiceOfValues();
+				for (GlobalType g : getAllGlobals(object)) {
+					ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(g);
+					choices.put(adapter.getObjectDescriptor().getTextValue(), g);
 				}
 				return choices;
 			}
-			
-			@Override
-			protected void internalSet(MultiInstanceLoopCharacteristics object, EStructuralFeature feature, Object value, int index) {
-				if (object.eContainer() instanceof SubProcess) {
-					SubProcess subprocess = (SubProcess) object.eContainer();
-					InputOutputSpecification ioSpec = subprocess.getIoSpecification();
-					Resource resource = getResource();
-					if (value instanceof ItemAwareElement) {
-						ItemAwareElement element = (ItemAwareElement) value;
-						DataOutput output = null;
-						OutputSet outputSet = null;
-						DataOutputAssociation outputAssociation = null;
-						if (ioSpec==null) {
-							ioSpec = Bpmn2ModelerFactory.create(resource, InputOutputSpecification.class);
-							subprocess.setIoSpecification(ioSpec);
-						}
-						else {
-							for (DataOutput dout : ioSpec.getDataOutputs()) {
-								if (dout == object.getLoopDataOutputRef()) {
-									output = dout;
-									break;
-								}
-							}
-						}
-						if (output == null)
-							output = Bpmn2ModelerFactory.create(resource, DataOutput.class);
-						output.setName(element.getId());
-						output.setItemSubjectRef(element.getItemSubjectRef());
-						output.setIsCollection(true);
-						if (!ioSpec.getDataOutputs().contains(output))
-							ioSpec.getDataOutputs().add(output);
-						
-						for (OutputSet os : ioSpec.getOutputSets()) {
-							if (os.getDataOutputRefs().contains(output)) {
-								outputSet = os;
-								break;
-							}
-						}
-						if (outputSet == null) {
-							if (ioSpec.getOutputSets().size()==0) {
-								outputSet = Bpmn2ModelerFactory.create(resource, OutputSet.class);
-								ioSpec.getOutputSets().add(outputSet);
-							}
-							else
-								outputSet = ioSpec.getOutputSets().get(0);
-						}
-						if (!outputSet.getDataOutputRefs().contains(output))
-							outputSet.getDataOutputRefs().add(output);
-
-						for (DataOutputAssociation doa : subprocess.getDataOutputAssociations()) {
-							if (doa.getSourceRef().size()==1 && doa.getSourceRef().get(0)==output) {
-								outputAssociation = doa;
-								break;
-							}
-						}
-						if (outputAssociation == null) {
-							outputAssociation = Bpmn2ModelerFactory.create(resource, DataOutputAssociation.class);
-							subprocess.getDataOutputAssociations().add(outputAssociation);
-						}
-						
-						outputAssociation.getSourceRef().clear();
-						outputAssociation.getSourceRef().add(output);
-						outputAssociation.setTargetRef(element);
-						
-						value = output;
-					}
-					else if (value==null) {
-						ItemAwareElement output = object.getLoopDataOutputRef();
-						if (ioSpec!=null) {
-							if (output!=null) {
-								for (DataOutput dout : ioSpec.getDataOutputs()) {
-									if (dout == output) {
-										ioSpec.getDataOutputs().remove(dout);
-										if (ioSpec.getOutputSets().size()>0) {
-											ioSpec.getOutputSets().get(0).getDataOutputRefs().remove(dout);
-											if (ioSpec.getOutputSets().get(0).getDataOutputRefs().size()==0)
-												ioSpec.getOutputSets().remove(0);
-										}
-										break;
-									}
-								}
-								int i = 0;
-								for (DataOutputAssociation doa : subprocess.getDataOutputAssociations()) {
-									if (doa.getSourceRef().size()>0 && doa.getSourceRef().get(0) == output) {
-										subprocess.getDataOutputAssociations().remove(i);
-										break;
-									}
-									++i;
-								}
-							}
-							if (ioSpec.getDataInputs().size()==0 && ioSpec.getDataOutputs().size()==0) {
-								subprocess.setIoSpecification(null);
-							}
-						}
-
-					}
-				}
-				super.internalSet(object, feature, value, index);
-			}
 		});
 	}
-
+	
+	private List<GlobalType> getAllGlobals(EObject object) {
+		List<GlobalType> results = new ArrayList<GlobalType>();
+		// navigate up to the Process from the given EObject
+		Process process = null;
+		while (object!=null) {
+			if (object instanceof Process) {
+				process = (Process) object;
+				break;
+			}
+			object = object.eContainer();
+		}
+		if (process!=null) {
+			for (Object g : ModelDecorator.getAllExtensionAttributeValues(process, GlobalType.class)) {
+				results.add((GlobalType)g);
+			}
+		}
+		return results;
+	}
 }
diff --git a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataInputPropertiesAdapter.java b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataInputPropertiesAdapter.java
index 4b4aad2..c676712 100644
--- a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataInputPropertiesAdapter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataInputPropertiesAdapter.java
@@ -58,11 +58,12 @@
 					text = dataInput.getId();
 
 				if (text!=null) {
-					if (dataInput.isIsCollection())
-						text += "[]"; //$NON-NLS-1$
-					String type = ExtendedPropertiesProvider.getTextValue(dataInput.getItemSubjectRef());
-					if (type!=null)
-						text += " (" + type + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+					// TODO: add CONTEXT_TEXT to Data Association inputs and outputs
+//					if (dataInput.isIsCollection())
+//						text += "[]"; //$NON-NLS-1$
+//					String type = ExtendedPropertiesProvider.getTextValue(dataInput.getItemSubjectRef());
+//					if (type!=null && !type.isEmpty())
+//						text += " (" + type + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 				}
 				return text;
 			}
diff --git a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataOutputPropertiesAdapter.java b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataOutputPropertiesAdapter.java
index 0a2eef3..a998c8f 100644
--- a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataOutputPropertiesAdapter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/DataOutputPropertiesAdapter.java
@@ -58,11 +58,12 @@
 					text = dataOutput.getId();
 
 				if (text!=null) {
-					if (dataOutput.isIsCollection())
-						text += "[]"; //$NON-NLS-1$
-					String type = ExtendedPropertiesProvider.getTextValue(dataOutput.getItemSubjectRef());
-					if (type!=null)
-						text += " (" + type + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+					// TODO: add CONTEXT_TEXT to Data Association inputs and outputs
+//					if (dataOutput.isIsCollection())
+//						text += "[]"; //$NON-NLS-1$
+//					String type = ExtendedPropertiesProvider.getTextValue(dataOutput.getItemSubjectRef());
+//					if (type!=null && !type.isEmpty())
+//						text += " (" + type + ")"; //$NON-NLS-1$ //$NON-NLS-2$
 				}
 				return text;
 			}
diff --git a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/ItemDefinitionPropertiesAdapter.java b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/ItemDefinitionPropertiesAdapter.java
index befdc17..29c24c1 100644
--- a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/ItemDefinitionPropertiesAdapter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/ItemDefinitionPropertiesAdapter.java
@@ -185,8 +185,9 @@
 		String name = ""; //$NON-NLS-1$
 		if (itemDefinition!=null) {
 			name = getStructureName(itemDefinition);
-			if (itemDefinition.isIsCollection())
-				name += "[]"; //$NON-NLS-1$
+			// TODO: add CONTEXT_TEXT to Data Association inputs and outputs
+//			if (itemDefinition.isIsCollection())
+//				name += "[]"; //$NON-NLS-1$
 		}
 		return name;
 	}
diff --git a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/MultiInstanceLoopCharacteristicsPropertiesAdapter.java b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/MultiInstanceLoopCharacteristicsPropertiesAdapter.java
index 7167888..6e702a4 100644
--- a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/MultiInstanceLoopCharacteristicsPropertiesAdapter.java
+++ b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/adapters/properties/MultiInstanceLoopCharacteristicsPropertiesAdapter.java
@@ -20,17 +20,25 @@
 import org.eclipse.bpmn2.Activity;
 import org.eclipse.bpmn2.Bpmn2Package;
 import org.eclipse.bpmn2.DataInput;
+import org.eclipse.bpmn2.DataInputAssociation;
 import org.eclipse.bpmn2.DataObject;
 import org.eclipse.bpmn2.DataObjectReference;
 import org.eclipse.bpmn2.DataOutput;
+import org.eclipse.bpmn2.DataOutputAssociation;
 import org.eclipse.bpmn2.InputOutputSpecification;
+import org.eclipse.bpmn2.InputSet;
+import org.eclipse.bpmn2.ItemAwareElement;
 import org.eclipse.bpmn2.MultiInstanceLoopCharacteristics;
+import org.eclipse.bpmn2.OutputSet;
 import org.eclipse.bpmn2.Process;
 import org.eclipse.bpmn2.SubProcess;
+import org.eclipse.bpmn2.Task;
 import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter;
 import org.eclipse.bpmn2.modeler.core.adapters.FeatureDescriptor;
 import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
 import org.eclipse.bpmn2.modeler.core.utils.ModelUtil;
+import org.eclipse.bpmn2.modeler.ui.adapters.properties.MultiInstanceLoopCharacteristicsPropertiesAdapter.LoopDataCollectionFeatureDescriptor;
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.EObject;
@@ -55,25 +63,24 @@
 	public MultiInstanceLoopCharacteristicsPropertiesAdapter(AdapterFactory adapterFactory, MultiInstanceLoopCharacteristics object) {
 		super(adapterFactory, object);
 
-		setFeatureDescriptor(LOOP_DATA_INPUT_REF, new LoopCharacteristicsDataIoFeatureDescriptor(this, object, LOOP_DATA_INPUT_REF));
 		setProperty(LOOP_DATA_INPUT_REF, UI_IS_MULTI_CHOICE, Boolean.TRUE);
 		setProperty(LOOP_DATA_INPUT_REF, UI_CAN_EDIT, Boolean.TRUE);
 		setProperty(LOOP_DATA_INPUT_REF, UI_CAN_CREATE_NEW, Boolean.TRUE);
-		
-//		setFeatureDescriptor(INPUT_DATA_ITEM, new LoopCharacteristicsDataIoFeatureDescriptor(adapterFactory,object, INPUT_DATA_ITEM));
-//		setProperty(INPUT_DATA_ITEM, UI_IS_MULTI_CHOICE, Boolean.TRUE);
 
-		setFeatureDescriptor(LOOP_DATA_OUTPUT_REF, new LoopCharacteristicsDataIoFeatureDescriptor(this, object, LOOP_DATA_OUTPUT_REF));
 		setProperty(LOOP_DATA_OUTPUT_REF, UI_IS_MULTI_CHOICE, Boolean.TRUE);
 		setProperty(LOOP_DATA_OUTPUT_REF, UI_CAN_EDIT, Boolean.TRUE);
 		setProperty(LOOP_DATA_OUTPUT_REF, UI_CAN_CREATE_NEW, Boolean.TRUE);
 
-//		setFeatureDescriptor(OUTPUT_DATA_ITEM, new LoopCharacteristicsDataIoFeatureDescriptor(adapterFactory,object, OUTPUT_DATA_ITEM));
-//		setProperty(OUTPUT_DATA_ITEM, UI_IS_MULTI_CHOICE, Boolean.TRUE);
+		setFeatureDescriptor(LOOP_DATA_INPUT_REF, new LoopDataInputCollectionFeatureDescriptor(this, object));
+		setFeatureDescriptor(INPUT_DATA_ITEM, new LoopInputDataItemFeatureDescriptor(this, object));
+
+		setFeatureDescriptor(LOOP_DATA_OUTPUT_REF, new LoopDataOutputCollectionFeatureDescriptor(this, object));
+		setFeatureDescriptor(OUTPUT_DATA_ITEM, new LoopOutputDataItemFeatureDescriptor(this, object));
 	}
 
 	/**
-	 * This class calculates the Loop Input/Output collections and Input/Output parameters that are in scope for the 
+	 * This is a base class for LoopDataInputCollectionFeatureDescriptor and LoopDataOutputCollectionFeatureDescriptor.
+	 * It calculates the Loop Input/Output collections and Input/Output parameters that are in scope for the 
 	 * Activity that owns this Multi-Instance Loop Characteristics object. From the BPMN2 spec:
 	 * 
 	 * Loop Data Input/Output (the collection):
@@ -86,12 +93,13 @@
 	 *   Activity’s InputOutputSpecification.
 	 *   The type of this Data Input/Output MUST be the scalar of the type defined for the loopDataInput/Output.
 	 */
-	protected class LoopCharacteristicsDataIoFeatureDescriptor extends FeatureDescriptor<MultiInstanceLoopCharacteristics> {
+	protected class LoopDataCollectionFeatureDescriptor extends FeatureDescriptor<MultiInstanceLoopCharacteristics> {
 
-		public LoopCharacteristicsDataIoFeatureDescriptor(
+		public LoopDataCollectionFeatureDescriptor(
 				ExtendedPropertiesAdapter<MultiInstanceLoopCharacteristics> owner,
 				MultiInstanceLoopCharacteristics object, EStructuralFeature feature) {
 			super(owner, object, feature);
+			Assert.isTrue(feature==LOOP_DATA_INPUT_REF || feature==LOOP_DATA_OUTPUT_REF);
 		}
 
 		@Override
@@ -99,19 +107,17 @@
 			EObject value = super.createFeature(resource, eclass);
 			// if the new object is the collection reference, we need to attach it to the
 			// activity's InputOutputSpecification.
-			if (feature==LOOP_DATA_INPUT_REF || feature==LOOP_DATA_OUTPUT_REF) {
-				Activity container = (Activity)ModelUtil.getContainer(object);
-				EStructuralFeature f = container.eClass().getEStructuralFeature("ioSpecification"); //$NON-NLS-1$
-				if (f!=null) {
-					InputOutputSpecification ioSpecification = (InputOutputSpecification)container.eGet(f);
-					if (ioSpecification==null) {
-						ioSpecification = Bpmn2ModelerFactory.createFeature(object.eResource(), container, f, InputOutputSpecification.class);
-					}
-					if (value instanceof DataInput)
-						ioSpecification.getDataInputs().add((DataInput)value);
-					else
-						ioSpecification.getDataOutputs().add((DataOutput)value);
+			Activity container = (Activity)ModelUtil.getContainer(object);
+			EStructuralFeature f = container.eClass().getEStructuralFeature("ioSpecification"); //$NON-NLS-1$
+			if (f!=null) {
+				InputOutputSpecification ioSpecification = (InputOutputSpecification)container.eGet(f);
+				if (ioSpecification==null) {
+					ioSpecification = Bpmn2ModelerFactory.createFeature(object.eResource(), container, f, InputOutputSpecification.class);
 				}
+				if (value instanceof DataInput)
+					ioSpecification.getDataInputs().add((DataInput)value);
+				else
+					ioSpecification.getDataOutputs().add((DataOutput)value);
 			}
 			return value;
 		}
@@ -122,57 +128,44 @@
 			
 			Activity container = (Activity)ModelUtil.getContainer(object);
 			List values = new ArrayList<EObject>();
-			if (feature == LOOP_DATA_INPUT_REF || feature == LOOP_DATA_OUTPUT_REF) {
-//				if (container instanceof Task)
-				{
-					EStructuralFeature f = container.eClass().getEStructuralFeature("ioSpecification"); //$NON-NLS-1$
-					if (f!=null) {
-						InputOutputSpecification ioSpecification = (InputOutputSpecification)container.eGet(f);
-						if (ioSpecification!=null) {
-							if (feature == LOOP_DATA_INPUT_REF)
-								values.addAll(ioSpecification.getDataInputs());
-							else
-								values.addAll(ioSpecification.getDataOutputs());
-						}
-					}
-				}
-//				else 
-				if (container instanceof SubProcess) {
-					// Collect all DataObjects from Process and SubProcess ancestors
-					// DataObjects are FlowElements, so we will have to weed those out from other FlowElements.
-					List<EObject> flowElements = ModelUtil.collectAncestorObjects(object, "flowElements", new Class[] {Process.class, SubProcess.class}); //$NON-NLS-1$
-					for (EObject fe : flowElements) {
-						if (fe instanceof DataObjectReference) {
-							fe = ((DataObjectReference)fe).getDataObjectRef();
-						}
-						if (!(fe instanceof DataObject)) {
-							fe = null;
-						}
-						if (fe!=null && !values.contains(fe))
-							values.add(fe);
-					}
-					// Collect all Properties from Process and SubProcess ancestors
-					EObject parent = container.eContainer();
-					while (parent!=null) {
-						if (parent instanceof Process) {
-							values.addAll(((Process)parent).getProperties());
-						}
-						if (parent instanceof SubProcess) {
-							values.addAll(((SubProcess)parent).getProperties());
-						}
-						parent = parent.eContainer();
-					}
+
+			EStructuralFeature f = container.eClass().getEStructuralFeature("ioSpecification"); //$NON-NLS-1$
+			if (f!=null) {
+				InputOutputSpecification ioSpecification = (InputOutputSpecification)container.eGet(f);
+				if (ioSpecification!=null) {
+					if (feature == LOOP_DATA_INPUT_REF)
+						values.addAll(ioSpecification.getDataInputs());
+					else
+						values.addAll(ioSpecification.getDataOutputs());
 				}
 			}
-			else {
-				// INPUT_DATA_ITEM or OUTPUT_DATA_ITEM feature
-				// TODO: This part of the spec is unclear to me. It looks like the Data Input/Output Items need to
-				// be contained in the MI Loop Characteristics. Something like this:
-				//
-				// <multiInstanceLoopCharacteristics id="MI_6">
-				//     <loopDataInputRef>DataObject_3</bpmn2:loopDataInputRef>
-				//     <inputDataItem xsi:type="bpmn2:tDataInput" id="DataInput_1" itemSubjectRef="ItemDefinition_1" name="input_param"/>
-				// </multiInstanceLoopCharacteristics>
+
+//			if (container instanceof SubProcess)
+			{
+				// Collect all DataObjects from Process and SubProcess ancestors
+				// DataObjects are FlowElements, so we will have to weed those out from other FlowElements.
+				List<EObject> flowElements = ModelUtil.collectAncestorObjects(object, "flowElements", new Class[] {Process.class, SubProcess.class}); //$NON-NLS-1$
+				for (EObject fe : flowElements) {
+					if (fe instanceof DataObjectReference) {
+						fe = ((DataObjectReference)fe).getDataObjectRef();
+					}
+					if (!(fe instanceof DataObject)) {
+						fe = null;
+					}
+					if (fe!=null && !values.contains(fe))
+						values.add(fe);
+				}
+				// Collect all Properties from Process and SubProcess ancestors
+				EObject parent = container.eContainer();
+				while (parent!=null) {
+					if (parent instanceof Process) {
+						values.addAll(((Process)parent).getProperties());
+					}
+					if (parent instanceof SubProcess) {
+						values.addAll(((SubProcess)parent).getProperties());
+					}
+					parent = parent.eContainer();
+				}
 			}
 			
 			if (values!=null) {
@@ -183,5 +176,540 @@
 			super.setChoiceOfValues(choices);
 			return super.getChoiceOfValues();
 		}
+		
+		@Override
+		public String getTextValue() {
+			Object value = getValue();
+			if (value!=null) {
+				return super.getChoiceString(value);
+			}					
+			return "";
+		}
+	}
+
+	protected class LoopDataInputCollectionFeatureDescriptor extends LoopDataCollectionFeatureDescriptor {
+		
+		public LoopDataInputCollectionFeatureDescriptor(
+				ExtendedPropertiesAdapter<MultiInstanceLoopCharacteristics> owner,
+				MultiInstanceLoopCharacteristics object) {
+			super(owner, object, LOOP_DATA_INPUT_REF);
+		}
+		
+		@Override
+		protected void internalSet(MultiInstanceLoopCharacteristics object, EStructuralFeature feature, Object value, int index) {
+			ItemAwareElement element = null;
+			if (value instanceof ItemAwareElement)
+				element = (ItemAwareElement) value;
+			
+			if (object.eContainer() instanceof Activity) {
+				value = setInputCollection(object, (Activity) object.eContainer(), element);
+			}
+			super.internalSet(object, feature, value, index);
+		}
+
+		@Override
+		public Object getValue() {
+			ItemAwareElement din = object.getLoopDataInputRef();
+			if (din==null)
+				return null;
+			// this is the LoopDataInputRef in the MI Loop Characteristics
+			if (object.eContainer() instanceof SubProcess) {
+				// get the name from the DataInput itself
+				return super.getValue();
+			}
+			else if (object.eContainer() instanceof Task) {
+				// get the name from the Task's mapped DataInput
+				Task task = (Task) object.eContainer();
+				for (DataInputAssociation dia : task.getDataInputAssociations()) {
+					if (din == dia.getTargetRef() && dia.getSourceRef().size()>0 && dia.getSourceRef().get(0) instanceof ItemAwareElement) {
+						return dia.getSourceRef().get(0);
+					}
+				}
+			}				
+			return null;
+		}
+	}
+	
+	protected class LoopDataOutputCollectionFeatureDescriptor extends LoopDataCollectionFeatureDescriptor {
+		
+		public LoopDataOutputCollectionFeatureDescriptor(
+				ExtendedPropertiesAdapter<MultiInstanceLoopCharacteristics> owner,
+				MultiInstanceLoopCharacteristics object) {
+			super(owner, object, LOOP_DATA_OUTPUT_REF);
+		}
+		
+		@Override
+		protected void internalSet(MultiInstanceLoopCharacteristics object, EStructuralFeature feature, Object value, int index) {
+			ItemAwareElement element = null;
+			if (value instanceof ItemAwareElement)
+				element = (ItemAwareElement) value;
+			
+			if (object.eContainer() instanceof Activity) {
+				value = setOutputCollection(object, (Activity) object.eContainer(), element);
+			}
+			super.internalSet(object, feature, value, index);
+		}
+
+		@Override
+		public Object getValue() {
+			ItemAwareElement dout = object.getLoopDataOutputRef();
+			if (dout==null)
+				return null;
+			// this is the DataInput in the MI Loop Characteristics
+			if (object.eContainer() instanceof SubProcess) {
+				// get the name from the DataInput itself
+				return super.getValue();
+			}
+			else if (object.eContainer() instanceof Task) {
+				// get the name from the Task's mapped DataInput
+				Task task = (Task) object.eContainer();
+				for (DataOutputAssociation doa : task.getDataOutputAssociations()) {
+					if (doa.getSourceRef().contains(dout) && doa.getTargetRef() instanceof ItemAwareElement) {
+						return doa.getTargetRef();
+					}
+				}
+			}				
+			return null;
+		}
+	}
+
+	protected class LoopDataItemFeatureDescriptor extends FeatureDescriptor<MultiInstanceLoopCharacteristics> {
+
+		public LoopDataItemFeatureDescriptor(ExtendedPropertiesAdapter<MultiInstanceLoopCharacteristics> owner,
+				MultiInstanceLoopCharacteristics object, EStructuralFeature feature) {
+			super(owner, object, feature);
+			Assert.isTrue(feature==INPUT_DATA_ITEM || feature==OUTPUT_DATA_ITEM);
+		}
+
+		@Override
+		public Hashtable<String, Object> getChoiceOfValues() {
+			Hashtable<String, Object> choices = new Hashtable<String, Object>();
+			EObject container = ModelUtil.getContainer(object);
+			// get the Property instances (a.k.a. "local variables") of the containing Process or SubProcess
+			if (container instanceof Activity) {
+				Activity activity = (Activity) container;
+				InputOutputSpecification iospec = activity.getIoSpecification();
+				if (iospec!=null) {
+					if (feature==INPUT_DATA_ITEM) {
+						for (ItemAwareElement e : iospec.getDataInputs()) {
+							if (object.getLoopDataInputRef()!=e)
+								choices.put(getChoiceString(e), e);
+						}
+					}
+					else {
+						for (ItemAwareElement e : iospec.getDataOutputs()) {
+							if (object.getLoopDataOutputRef()!=e)
+								choices.put(getChoiceString(e), e);
+						}
+					}
+				}
+			}
+			return choices;
+		}
+		
+		@Override
+		public String getTextValue() {
+			Object value = getValue();
+			if (value!=null) {
+				return super.getChoiceString(value);
+			}					
+			return "";
+		}
+	}
+
+	protected class LoopInputDataItemFeatureDescriptor extends LoopDataItemFeatureDescriptor {
+
+		public LoopInputDataItemFeatureDescriptor(ExtendedPropertiesAdapter<MultiInstanceLoopCharacteristics> owner,
+				MultiInstanceLoopCharacteristics object) {
+			super(owner, object, INPUT_DATA_ITEM);
+		}
+
+		@Override
+		protected void internalSet(MultiInstanceLoopCharacteristics object, EStructuralFeature feature, Object value, int index) {
+			ItemAwareElement element = null;
+			if (value instanceof ItemAwareElement)
+				element = (ItemAwareElement) value;
+			
+			if (object.eContainer() instanceof SubProcess) {
+				value = setSubProcessInputItem(object, (SubProcess) object.eContainer(), element);
+			}
+			else if (object.eContainer() instanceof Task) {
+				value = setTaskInputItem(object, (Task) object.eContainer(), element);
+			}				
+			super.internalSet(object, feature, value, index);
+		}
+
+		@Override
+		public Object getValue() {
+			DataInput din = object.getInputDataItem();
+			if (din==null)
+				return null;
+			// this is the DataInput in the MI Loop Characteristics
+			if (object.eContainer() instanceof SubProcess) {
+				// get the name from the DataInput itself
+				return din;
+			}
+			else if (object.eContainer() instanceof Task) {
+				// get the name from the Task's mapped DataInput
+				Task task = (Task) object.eContainer();
+				for (DataInputAssociation dia : task.getDataInputAssociations()) {
+					if (dia.getSourceRef().contains(din) && dia.getTargetRef() instanceof DataInput) {
+						return dia.getTargetRef();
+					}
+				}
+			}				
+			return null;
+		}
+	}
+
+	protected class LoopOutputDataItemFeatureDescriptor extends LoopDataItemFeatureDescriptor {
+
+		public LoopOutputDataItemFeatureDescriptor(ExtendedPropertiesAdapter<MultiInstanceLoopCharacteristics> owner,
+				MultiInstanceLoopCharacteristics object) {
+			super(owner, object, OUTPUT_DATA_ITEM);
+		}
+
+		@Override
+		protected void internalSet(MultiInstanceLoopCharacteristics object, EStructuralFeature feature, Object value, int index) {
+			ItemAwareElement element = null;
+			if (value instanceof ItemAwareElement)
+				element = (ItemAwareElement) value;
+			
+			if (object.eContainer() instanceof SubProcess) {
+				value = setSubProcessOutputItem(object, (SubProcess) object.eContainer(), element);
+			}
+			else if (object.eContainer() instanceof Task) {
+				value = setTaskOutputItem(object, (Task) object.eContainer(), element);
+			}				
+			super.internalSet(object, feature, value, index);
+		}
+
+		@Override
+		public Object getValue() {
+			DataOutput dout = object.getOutputDataItem();
+			if (dout==null)
+				return null;
+			// this is the DataOutput in the MI Loop Characteristics
+			if (object.eContainer() instanceof SubProcess) {
+				// get the name from the DataOutput itself
+				return dout;
+			}
+			else if (object.eContainer() instanceof Task) {
+				// get the name from the Task's mapped DataOutput
+				Task task = (Task) object.eContainer();
+				for (DataOutputAssociation dia : task.getDataOutputAssociations()) {
+					if (dia.getTargetRef()==dout && dia.getSourceRef().size()>0 && dia.getSourceRef().get(0) instanceof DataOutput) {
+						return dia.getSourceRef().get(0);
+					}
+				}
+			}				
+			return null;
+		}
+	}
+	
+	////////////////////////////////////////////////////////////////////////////////////////////
+	//
+	////////////////////////////////////////////////////////////////////////////////////////////
+
+	/**
+	 * Set or clear the Loop Data Input Reference feature of the given
+	 * MultiInstancLoopCharacteristics object.
+	 * 
+	 * This also manages the Activity's Data Inputs and Input Sets in the
+	 * IOSpecificaiont as well as the Activity's DataInputAssociations.
+	 * 
+	 * @param milc
+	 *            the MultiInstancLoopCharacteristics object
+	 * @param subprocess
+	 *            the affected Activity
+	 * @param element
+	 *            the new value for the Loop Data Input
+	 * @see MultiInstanceLoopCharacteristics#setLoopDataOutputRef(ItemAwareElement)
+	 */
+	private ItemAwareElement setInputCollection(MultiInstanceLoopCharacteristics milc, Activity subprocess, ItemAwareElement element) {
+		InputOutputSpecification ioSpec = subprocess.getIoSpecification();
+		Resource resource = getResource();
+		if (element!=null) {
+			DataInput input = null;
+			InputSet inputSet = null;
+			DataInputAssociation inputAssociation = null;
+			if (ioSpec==null) {
+				ioSpec = Bpmn2ModelerFactory.create(resource, InputOutputSpecification.class);
+				subprocess.setIoSpecification(ioSpec);
+			}
+			else {
+				for (DataInput din : ioSpec.getDataInputs()) {
+					if (din == milc.getLoopDataInputRef()) {
+						input = din;
+						break;
+					}
+				}
+			}
+			if (input == null)
+				input = Bpmn2ModelerFactory.create(resource, DataInput.class);
+			input.setName(element.getId());
+			input.setItemSubjectRef(element.getItemSubjectRef());
+			input.setIsCollection(true);
+			if (!ioSpec.getDataInputs().contains(input))
+				ioSpec.getDataInputs().add(input);
+			
+			for (InputSet is : ioSpec.getInputSets()) {
+				if (is.getDataInputRefs().contains(input)) {
+					inputSet = is;
+					break;
+				}
+			}
+			if (inputSet == null) {
+				if (ioSpec.getInputSets().size()==0) {
+					inputSet = Bpmn2ModelerFactory.create(resource, InputSet.class);
+					ioSpec.getInputSets().add(inputSet);
+				}
+				else
+					inputSet = ioSpec.getInputSets().get(0);
+			}
+			if (!inputSet.getDataInputRefs().contains(input))
+				inputSet.getDataInputRefs().add(input);
+
+			for (DataInputAssociation dia : subprocess.getDataInputAssociations()) {
+				if (dia.getTargetRef()==input) {
+					inputAssociation = dia;
+					break;
+				}
+			}
+			if (inputAssociation == null) {
+				inputAssociation = Bpmn2ModelerFactory.create(resource, DataInputAssociation.class);
+				subprocess.getDataInputAssociations().add(inputAssociation);
+			}
+			
+			inputAssociation.setTargetRef(input);
+			inputAssociation.getSourceRef().clear();
+			inputAssociation.getSourceRef().add(element);
+			
+			element = input;
+		}
+		else {
+			ItemAwareElement input = milc.getLoopDataInputRef();
+			if (ioSpec!=null) {
+				if (input!=null) {
+					for (DataInput din : ioSpec.getDataInputs()) {
+						if (din == input) {
+							ioSpec.getDataInputs().remove(din);
+							if (ioSpec.getInputSets().size()>0) {
+								ioSpec.getInputSets().get(0).getDataInputRefs().remove(din);
+								if (ioSpec.getInputSets().get(0).getDataInputRefs().size()==0)
+									ioSpec.getInputSets().remove(0);
+							}
+							break;
+						}
+					}
+					int i = 0;
+					for (DataInputAssociation dia : subprocess.getDataInputAssociations()) {
+						if (dia.getTargetRef() == input) {
+							subprocess.getDataInputAssociations().remove(i);
+							break;
+						}
+						++i;
+					}
+				}
+				if (ioSpec.getDataInputs().size()==0 && ioSpec.getDataOutputs().size()==0) {
+					subprocess.setIoSpecification(null);
+				}
+			}
+		}
+		
+		return element;
+	}
+	
+	/**
+	 * Set or clear the Loop Data Output Reference feature of the given
+	 * MultiInstancLoopCharacteristics object.
+	 * 
+	 * This also manages the Activity's Data Outputs and Output Sets in the
+	 * IOSpecificaiont as well as the Activity's DataOutputAssociations.
+	 * 
+	 * @param milc
+	 *            the MultiInstancLoopCharacteristics object
+	 * @param activity
+	 *            the affected Activity
+	 * @param element
+	 *            the new value for the Loop Data Output
+	 * @see MultiInstanceLoopCharacteristics#setLoopDataOutputRef(ItemAwareElement)
+	 */
+	private ItemAwareElement setOutputCollection(MultiInstanceLoopCharacteristics milc, Activity activity, ItemAwareElement element) {
+		InputOutputSpecification ioSpec = activity.getIoSpecification();
+		Resource resource = getResource();
+		if (element!=null) {
+			DataOutput output = null;
+			OutputSet outputSet = null;
+			DataOutputAssociation outputAssociation = null;
+			if (ioSpec==null) {
+				ioSpec = Bpmn2ModelerFactory.create(resource, InputOutputSpecification.class);
+				activity.setIoSpecification(ioSpec);
+			}
+			else {
+				for (DataOutput dout : ioSpec.getDataOutputs()) {
+					if (dout == milc.getLoopDataOutputRef()) {
+						output = dout;
+						break;
+					}
+				}
+			}
+			if (output == null)
+				output = Bpmn2ModelerFactory.create(resource, DataOutput.class);
+			output.setName(element.getId());
+			output.setItemSubjectRef(element.getItemSubjectRef());
+			output.setIsCollection(true);
+			if (!ioSpec.getDataOutputs().contains(output))
+				ioSpec.getDataOutputs().add(output);
+			
+			for (OutputSet os : ioSpec.getOutputSets()) {
+				if (os.getDataOutputRefs().contains(output)) {
+					outputSet = os;
+					break;
+				}
+			}
+			if (outputSet == null) {
+				if (ioSpec.getOutputSets().size()==0) {
+					outputSet = Bpmn2ModelerFactory.create(resource, OutputSet.class);
+					ioSpec.getOutputSets().add(outputSet);
+				}
+				else
+					outputSet = ioSpec.getOutputSets().get(0);
+			}
+			if (!outputSet.getDataOutputRefs().contains(output))
+				outputSet.getDataOutputRefs().add(output);
+
+			for (DataOutputAssociation doa : activity.getDataOutputAssociations()) {
+				if (doa.getSourceRef().size()==1 && doa.getSourceRef().get(0)==output) {
+					outputAssociation = doa;
+					break;
+				}
+			}
+			if (outputAssociation == null) {
+				outputAssociation = Bpmn2ModelerFactory.create(resource, DataOutputAssociation.class);
+				activity.getDataOutputAssociations().add(outputAssociation);
+			}
+			
+			outputAssociation.getSourceRef().clear();
+			outputAssociation.getSourceRef().add(output);
+			outputAssociation.setTargetRef(element);
+			
+			element = output;
+		}
+		else {
+			ItemAwareElement output = milc.getLoopDataOutputRef();
+			if (ioSpec!=null) {
+				if (output!=null) {
+					for (DataOutput dout : ioSpec.getDataOutputs()) {
+						if (dout == output) {
+							ioSpec.getDataOutputs().remove(dout);
+							if (ioSpec.getOutputSets().size()>0) {
+								ioSpec.getOutputSets().get(0).getDataOutputRefs().remove(dout);
+								if (ioSpec.getOutputSets().get(0).getDataOutputRefs().size()==0)
+									ioSpec.getOutputSets().remove(0);
+							}
+							break;
+						}
+					}
+					int i = 0;
+					for (DataOutputAssociation doa : activity.getDataOutputAssociations()) {
+						if (doa.getSourceRef().size()>0 && doa.getSourceRef().get(0) == output) {
+							activity.getDataOutputAssociations().remove(i);
+							break;
+						}
+						++i;
+					}
+				}
+				if (ioSpec.getDataInputs().size()==0 && ioSpec.getDataOutputs().size()==0) {
+					activity.setIoSpecification(null);
+				}
+			}
+
+		}
+		return element;
+	}
+	
+	private ItemAwareElement setSubProcessInputItem(MultiInstanceLoopCharacteristics milc, SubProcess subprocess, ItemAwareElement element) {
+		return element;
+	}
+
+	private ItemAwareElement setSubProcessOutputItem(MultiInstanceLoopCharacteristics milc, SubProcess subprocess, ItemAwareElement element) {
+		return element;
+	}
+
+	private ItemAwareElement setTaskInputItem(MultiInstanceLoopCharacteristics milc, Task task, ItemAwareElement element) {
+		Resource resource = task.eResource();
+		// find the old DataInputAssociation for the current MI Input Data Item
+		// and delete it because it will be replaced by a new one.
+		DataInput oldDin = milc.getInputDataItem();
+		if (oldDin!=null) {
+			for (DataInputAssociation dia : task.getDataInputAssociations()) {
+				if (dia.getSourceRef().contains(oldDin)) {
+					task.getDataInputAssociations().remove(dia);
+					break;
+				}
+			}
+		}		
+		
+		// find the DataInputAssociation for this DataInput, if it exists
+		DataInputAssociation dataInputAssociation = null;
+		for (DataInputAssociation dia : task.getDataInputAssociations()) {
+			if (dia.getTargetRef() == element) {
+				dataInputAssociation = dia;
+				break;
+			}
+		}
+		if (dataInputAssociation==null) {
+			// not found? create one!
+			dataInputAssociation = Bpmn2ModelerFactory.create(resource, DataInputAssociation.class);
+			task.getDataInputAssociations().add(dataInputAssociation);
+			dataInputAssociation.setTargetRef(element);
+		}
+		// create a new DataInput for the MI loop input item
+		// and map it to the given element
+		DataInput din = Bpmn2ModelerFactory.create(resource, DataInput.class);
+		din.setName(((DataInput)element).getName());
+		din.setItemSubjectRef(element.getItemSubjectRef());
+		dataInputAssociation.getSourceRef().clear();
+		dataInputAssociation.getSourceRef().add(din);
+		return din;
+	}
+
+	private ItemAwareElement setTaskOutputItem(MultiInstanceLoopCharacteristics milc, Task task, ItemAwareElement element) {
+		Resource resource = task.eResource();
+		// find the old DataOutputAssociation for the current MI Output Data Item
+		// and delete it because it will be replaced by a new one.
+		DataOutput oldDout = milc.getOutputDataItem();
+		if (oldDout!=null) {
+			for (DataOutputAssociation doa : task.getDataOutputAssociations()) {
+				if (doa.getTargetRef() == oldDout) {
+					task.getDataOutputAssociations().remove(doa);
+					break;
+				}
+			}
+		}		
+		
+		// find the DataOutputAssociation for this DataOutput, if it exists
+		DataOutputAssociation dataOutputAssociation = null;
+		for (DataOutputAssociation doa : task.getDataOutputAssociations()) {
+			if (doa.getSourceRef().contains(element)) {
+				dataOutputAssociation = doa;
+				break;
+			}
+		}
+		if (dataOutputAssociation==null) {
+			// not found? create one!
+			dataOutputAssociation = Bpmn2ModelerFactory.create(resource, DataOutputAssociation.class);
+			task.getDataOutputAssociations().add(dataOutputAssociation);
+			dataOutputAssociation.getSourceRef().clear();
+			dataOutputAssociation.getSourceRef().add(element);
+		}
+		// create a new DataOutput for the MI loop input item
+		// and map it to the given element
+		DataOutput dout = Bpmn2ModelerFactory.create(resource, DataOutput.class);
+		dout.setName(((DataOutput)element).getName());
+		dout.setItemSubjectRef(element.getItemSubjectRef());
+		dataOutputAssociation.setTargetRef(dout);
+		return dout;
 	}
 }
diff --git a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/property/tasks/MultiInstanceLoopCharacteristicsDetailComposite.java b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/property/tasks/MultiInstanceLoopCharacteristicsDetailComposite.java
index 891d724..f62c7fc 100644
--- a/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/property/tasks/MultiInstanceLoopCharacteristicsDetailComposite.java
+++ b/plugins/org.eclipse.bpmn2.modeler.ui/src/org/eclipse/bpmn2/modeler/ui/property/tasks/MultiInstanceLoopCharacteristicsDetailComposite.java
@@ -16,8 +16,12 @@
 import org.eclipse.bpmn2.DataOutput;
 import org.eclipse.bpmn2.Expression;
 import org.eclipse.bpmn2.FormalExpression;
+import org.eclipse.bpmn2.InputOutputSpecification;
+import org.eclipse.bpmn2.ItemAwareElement;
 import org.eclipse.bpmn2.MultiInstanceBehavior;
 import org.eclipse.bpmn2.MultiInstanceLoopCharacteristics;
+import org.eclipse.bpmn2.SubProcess;
+import org.eclipse.bpmn2.Task;
 import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesProvider;
 import org.eclipse.bpmn2.modeler.core.adapters.InsertionAdapter;
 import org.eclipse.bpmn2.modeler.core.merrimac.clad.AbstractBpmn2PropertySection;
@@ -31,7 +35,9 @@
 import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.FeatureEditingDialog;
 import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.ObjectEditor;
 import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.TextAndButtonObjectEditor;
+import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
 import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
+import org.eclipse.core.runtime.Assert;
 import org.eclipse.emf.ecore.EAttribute;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.EObject;
@@ -652,14 +658,13 @@
 							};
 							editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Input_Data_Label);
 
-
-							DataInput input = lc.getInputDataItem();
-							if (input==null) {
-								input = createModelObject(DataInput.class);
-								input.setName("");
-								InsertionAdapter.add(lc, PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem(), input);
+							if (be.eContainer() instanceof SubProcess) {
+								editor = new LoopDataItemObjectEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem());
 							}
-							editor = new DataInputOutputObjectEditor(this, input, PACKAGE.getDataInput_Name());
+							else {
+								// must be a Task
+								editor = new LoopDataItemSelectionEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem());
+							}
 							editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Input_Parameter_Label);
 						}
 					};
@@ -684,13 +689,13 @@
 							editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Output_Data_Label);
 							
 							
-							DataOutput output = lc.getOutputDataItem();
-							if (output==null) {
-								output = createModelObject(DataOutput.class);
-								output.setName("");
-								InsertionAdapter.add(lc, PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem(), output);
+							if (be.eContainer() instanceof SubProcess) {
+								editor = new LoopDataItemObjectEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem());
 							}
-							editor = new DataInputOutputObjectEditor(this, output, PACKAGE.getDataOutput_Name());
+							else {
+								// must be a Task
+								editor = new LoopDataItemSelectionEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem());
+							}
 							editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Output_Parameter_Label);
 						}
 					};
@@ -791,14 +796,50 @@
 	}
 	
 
-	public class DataInputOutputObjectEditor extends TextAndButtonObjectEditor {
-		public DataInputOutputObjectEditor(AbstractDetailComposite parent, EObject object, EStructuralFeature feature) {
+	private class LoopDataItemObjectEditor extends TextAndButtonObjectEditor {
+		
+		/**
+		 * The DataInput or DataOutput element of the MI InputDataItem or OutputDataItem
+		 */
+		ItemAwareElement element;
+		/**
+		 * The "name" feature of the above element
+		 */
+		EStructuralFeature elementFeature;
+		boolean isInput = false;
+		
+		public LoopDataItemObjectEditor(AbstractDetailComposite parent, MultiInstanceLoopCharacteristics object, EStructuralFeature feature) {
 			super(parent, object, feature);
+			if (feature==PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem()) {
+				isInput = true;
+				element = object.getInputDataItem();
+				elementFeature = PACKAGE.getDataInput_Name();
+			}
+			else if (feature==PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem()) {
+				isInput = false;
+				element = object.getOutputDataItem();
+				elementFeature = PACKAGE.getDataOutput_Name();
+			}
+			else
+				Assert.isTrue(false);
+			
+			if (element==null) {
+				if (isInput) {
+					element = createModelObject(DataInput.class);
+					element.eSet(elementFeature, "");
+					InsertionAdapter.add(object, PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem(), element);
+				}
+				else {
+					element = createModelObject(DataOutput.class);
+					element.eSet(elementFeature, "");
+					InsertionAdapter.add(object, PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem(), element);
+				}
+			}
 		}
 
 		@Override
 		protected void buttonClicked(int buttonId) {
-			FeatureEditingDialog dialog = new FeatureEditingDialog(getDiagramEditor(), object, Bpmn2Package.eINSTANCE.getItemAwareElement_ItemSubjectRef(), object);
+			FeatureEditingDialog dialog = new FeatureEditingDialog(getDiagramEditor(), element, Bpmn2Package.eINSTANCE.getItemAwareElement_ItemSubjectRef(), element);
 			if ( dialog.open() == Window.OK) {
 				this.updateText();
 			}
@@ -806,15 +847,47 @@
 
 		@Override
 		protected String getText() {
-			String text = null;
-			EStructuralFeature f = object.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
-			if (f!=null) {
-				text = (String)object.eGet(f);
-			}
+			String text = (String)element.eGet(elementFeature);
 			if (text==null)
 				return ""; //$NON-NLS-1$
 			return text;
 		}
 	};
 
+	private class LoopDataItemSelectionEditor extends ComboObjectEditor {
+
+		InputOutputSpecification ioSpec;
+		EStructuralFeature ioSpecFeature;
+		boolean isInput = false;
+		
+		public LoopDataItemSelectionEditor(AbstractDetailComposite parent, MultiInstanceLoopCharacteristics object, EStructuralFeature feature) {
+			super(parent, object, feature);
+			if (feature==PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem()) {
+				isInput = true;
+				ioSpecFeature = PACKAGE.getInputOutputSpecification_DataInputs();
+			}
+			else if (feature==PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem()) {
+				isInput = false;
+				ioSpecFeature = PACKAGE.getInputOutputSpecification_DataOutputs();
+			}
+			else
+				Assert.isTrue(false);
+		}
+
+		@Override
+		protected FeatureEditingDialog createFeatureEditingDialog(EObject value) {
+			// In this case the container is the I/O Specification of
+			// the Task that owns the "object" which is a instance of
+			// a MultiInstanceLoopCharacteristics
+			Task task = (Task) object.eContainer();
+			ioSpec = task.getIoSpecification();
+			if (ioSpec==null) {
+				ioSpec = Bpmn2ModelerFactory.create(
+						task.eResource(), InputOutputSpecification.class);
+				InsertionAdapter.add(task, PACKAGE.getActivity_IoSpecification(), ioSpec);
+			}
+			return new FeatureEditingDialog(getDiagramEditor(), ioSpec, ioSpecFeature, value);
+		}
+
+	}
 }