/******************************************************************************* * 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 *******************************************************************************/ package org.eclipse.bpmn2.modeler.ui.property.tasks; import java.util.Hashtable; import java.util.Map.Entry; import org.eclipse.bpmn2.Activity; 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.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; import org.eclipse.bpmn2.modeler.core.merrimac.clad.AbstractDetailComposite; import org.eclipse.bpmn2.modeler.core.merrimac.clad.AbstractListComposite; import org.eclipse.bpmn2.modeler.core.merrimac.clad.AbstractPropertiesProvider; import org.eclipse.bpmn2.modeler.core.merrimac.clad.DefaultDetailComposite; import org.eclipse.bpmn2.modeler.core.merrimac.clad.PropertiesCompositeFactory; import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.BooleanObjectEditor; import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.ComboObjectEditor; 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; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.graphiti.ui.editor.DiagramEditor; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; public class MultiInstanceLoopCharacteristicsDetailComposite extends DefaultDetailComposite { public enum InstanceType { None, DataInput, LoopCardinality }; ComboObjectEditor throwBehaviorEditor; ComboObjectEditor noneBehaviorEventEditor; ComboObjectEditor oneBehaviorEventEditor; AbstractListComposite complexBehaviorList; ObjectEditor isSequentialEditor; boolean completionConditionWidgetsShowing; Composite completionConditionWidgets; AbstractDetailComposite completionConditionEditor; boolean loopCardinalityWidgetsShowing; Composite instanceWidgets; Button loopCardinalityButton; Composite loopCardinalityWidgets; AbstractDetailComposite loopCardinalityEditor; boolean loopDataInputWidgetsShowing; Button loopDataInputButton; Composite loopDataInputWidgets; AbstractDetailComposite loopDataInputEditor; boolean loopDataOutputWidgetsShowing; Button producesOutputButton; Composite loopDataOutputWidgets; AbstractDetailComposite loopDataOutputEditor; boolean updatingWidgets; public MultiInstanceLoopCharacteristicsDetailComposite(Composite parent, int style) { super(parent, style); } public MultiInstanceLoopCharacteristicsDetailComposite(AbstractBpmn2PropertySection section) { super(section); } @Override public AbstractPropertiesProvider getPropertiesProvider(EObject object) { if (propertiesProvider==null) { propertiesProvider = new AbstractPropertiesProvider(object) { String[] properties = new String[] { "anyAttribute", //$NON-NLS-1$ "isSequential", //$NON-NLS-1$ "inputDataItem", //$NON-NLS-1$ "outputDataItem", //$NON-NLS-1$ "loopDataInputRef", //$NON-NLS-1$ "loopDataOutputRef", //$NON-NLS-1$ "completionCondition", //$NON-NLS-1$ "loopCardinality", //$NON-NLS-1$ "behavior", //$NON-NLS-1$ "noneBehaviorEventRef", //$NON-NLS-1$ "oneBehaviorEventRef", //$NON-NLS-1$ "complexBehaviorDefinition", //$NON-NLS-1$ }; @Override public String[] getProperties() { return properties; } }; } return propertiesProvider; } @Override protected void cleanBindings() { super.cleanBindings(); throwBehaviorEditor = null; noneBehaviorEventEditor = null; oneBehaviorEventEditor = null; complexBehaviorList = null; instanceWidgets = null; loopCardinalityButton = null; loopDataInputButton = null; loopCardinalityWidgets = null; loopDataInputWidgets = null; loopDataInputEditor = null; loopCardinalityEditor = null; loopDataOutputWidgets = null; isSequentialEditor = null; loopDataOutputEditor = null; } public void createBindings(EObject be) { // super.createBindings(be); createWidgets(); } private MultiInstanceLoopCharacteristics getBO() { return (MultiInstanceLoopCharacteristics)getBusinessObject(); } private void createWidgets() { Label label; //////////////////////// // "sequential" checkbox if (isEnabled("isSequential")) { //$NON-NLS-1$ isSequentialEditor = new BooleanObjectEditor(this, getBO(), PACKAGE.getMultiInstanceLoopCharacteristics_IsSequential()) { public boolean setValue(final Object result) { Object oldValue = getBusinessObjectDelegate().getValue(object, feature); if (oldValue!=result && !oldValue.equals(result)) { TransactionalEditingDomain editingDomain = getDiagramEditor().getEditingDomain(); editingDomain.getCommandStack().execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { getBusinessObjectDelegate().setValue(object, feature, button.getSelection()); // This little bit of java jimnastics is needed to update the multi-instance marker on the activity. // Because Graphiti's Resource change listener will only invoke an Update Feature on Pictogram Elements // that are linked to business model objects; a change to the "is sequential" boolean attribute in the // MultiInstanceLoopCharacteristics will not fire an update (the MI object is not directly linked // to any PE). We therefore force a change to the containing Activity object, which IS linked to a // Pictogram Element, and thereby cause the multi-instance decorator to change from 3 vertical bars to // 3 horizontal bars (or vice-versa) whenever the "is sequential" checkbox changes state. Activity activity = (Activity)getBO().eContainer(); int n = activity.getCompletionQuantity(); activity.setCompletionQuantity(n+1); activity.setCompletionQuantity(n); } }); } return true; } }; isSequentialEditor.createControl(getAttributesParent(),Messages.MultiInstanceLoopCharacteristicsDetailComposite_Sequential_Label); isSequentialEditor.getControl().addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { showCompletionConditionWidgets(getBO().isIsSequential()); redrawPage(); } }); } if (isEnabled("completionCondition")) { //$NON-NLS-1$ // completion condition expression completionConditionWidgets = toolkit.createComposite(getAttributesParent(), SWT.NONE); completionConditionWidgets.setLayout(new GridLayout(1,false)); completionConditionWidgets.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,true,3,1)); // initially hidden completionConditionWidgets.setVisible(false); ((GridData)completionConditionWidgets.getLayoutData()).exclude = true; } //////////////////////// // radio buttons for number of instances controls if (isEnabled("loopCardinality") && isEnabled("loopDataInputRef")) { //$NON-NLS-1$ //$NON-NLS-2$ label = toolkit.createLabel(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Number_Of_Instances); label.setLayoutData(new GridData(SWT.RIGHT,SWT.TOP,false,false,1,1)); loopCardinalityButton = toolkit.createButton(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Integer_Expression_Button, SWT.RADIO); loopCardinalityButton.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,false,1,1)); loopCardinalityButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (loopCardinalityButton.getSelection()) { showLoopDataInputWidgets(false); showLoopCardinalityWidgets(true); redrawPage(); } } }); loopDataInputButton = toolkit.createButton(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Collection_Button, SWT.RADIO); loopDataInputButton.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,true,false,1,1)); loopDataInputButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (loopDataInputButton.getSelection()) { showLoopCardinalityWidgets(false); showLoopDataInputWidgets(true); redrawPage(); } } }); } //////////////////////// // instances control composite instanceWidgets = toolkit.createComposite(getAttributesParent(), SWT.NONE); instanceWidgets.setLayout(new GridLayout(3,false)); instanceWidgets.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,3,1)); if (isEnabled("loopCardinality") && isEnabled("loopDataInputRef")) { //$NON-NLS-1$ //$NON-NLS-2$ // initially hidden instanceWidgets.setVisible(false); ((GridData)instanceWidgets.getLayoutData()).exclude = true; } if (isEnabled("loopCardinality")) { //$NON-NLS-1$ // expression loopCardinalityWidgets = toolkit.createComposite(instanceWidgets, SWT.NONE); loopCardinalityWidgets.setLayout(new GridLayout(1,false)); loopCardinalityWidgets.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,true,3,1)); } if (isEnabled("loopDataInputRef")) { //$NON-NLS-1$ // data collection loopDataInputWidgets = toolkit.createComposite(instanceWidgets, SWT.NONE); loopDataInputWidgets.setLayout(new GridLayout(3,false)); loopDataInputWidgets.setLayoutData(new GridData(SWT.FILL,SWT.TOP,true,true,3,1)); } //////////////////////// // produces output checkbox if (isEnabled("loopDataOutputRef")) { //$NON-NLS-1$ label = toolkit.createLabel(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Produces_Output_Label); label.setLayoutData(new GridData(SWT.RIGHT,SWT.TOP,false,false,1,1)); producesOutputButton = toolkit.createButton(getAttributesParent(), "", SWT.CHECK); //$NON-NLS-1$ producesOutputButton.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,true,false,2,1)); producesOutputButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { showLoopDataOutputWidgets(producesOutputButton.getSelection()); redrawPage(); } }); //////////////////////// // output data collection composite loopDataOutputWidgets = toolkit.createComposite(getAttributesParent(), SWT.NONE); loopDataOutputWidgets.setLayout(new GridLayout(3,false)); loopDataOutputWidgets.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true,3,1)); // initially hidden loopDataOutputWidgets.setVisible(false); ((GridData)loopDataOutputWidgets.getLayoutData()).exclude = true; } //////////////////////// // throw behavior combo and related widgets if (isEnabled("behavior")) { //$NON-NLS-1$ this.bindAttribute(getAttributesParent(), getBO(), "behavior", Messages.MultiInstanceLoopCharacteristicsDetailComposite_Throw_Behavior_Label); //$NON-NLS-1$ this.bindReference(getAttributesParent(), getBO(), PACKAGE.getMultiInstanceLoopCharacteristics_NoneBehaviorEventRef()); this.bindReference(getAttributesParent(), getBO(), PACKAGE.getMultiInstanceLoopCharacteristics_OneBehaviorEventRef()); this.bindList(getBO(), PACKAGE.getMultiInstanceLoopCharacteristics_ComplexBehaviorDefinition()); } updateWidgets(); } private void updateWidgets() { MultiInstanceLoopCharacteristics lc = getBO(); showCompletionConditionWidgets(lc.isIsSequential()); if (lc!=null && !updatingWidgets) { updatingWidgets = true; switch (getInstanceType()) { case None: if (loopCardinalityButton!=null) loopCardinalityButton.setSelection(false); if (loopDataInputButton!=null) loopDataInputButton.setSelection(false); loopDataInputWidgetsShowing = true; loopCardinalityWidgetsShowing = true; showLoopDataInputWidgets(false); showLoopCardinalityWidgets(false); break; case LoopCardinality: if (loopCardinalityButton!=null) loopCardinalityButton.setSelection(true); if (loopDataInputButton!=null) loopDataInputButton.setSelection(false); showLoopDataInputWidgets(false); showLoopCardinalityWidgets(true); break; case DataInput: if (loopCardinalityButton!=null) loopCardinalityButton.setSelection(false); if (loopDataInputButton!=null) loopDataInputButton.setSelection(true); showLoopCardinalityWidgets(false); showLoopDataInputWidgets(true); break; } if (producesOutputButton!=null) { boolean producesOutput = (lc.getLoopDataOutputRef()!=null || lc.getOutputDataItem()!=null); producesOutputButton.setSelection(producesOutput); showLoopDataOutputWidgets(producesOutput); } } updatingWidgets = false; } private InstanceType getInstanceType() { if (isEnabled("loopCardinality") && isEnabled("loopDataInputRef")) { //$NON-NLS-1$ //$NON-NLS-2$ MultiInstanceLoopCharacteristics lc = getBO(); if (lc.getLoopDataInputRef()==null && lc.getInputDataItem()==null) { if (lc.getLoopCardinality()==null) return InstanceType.None; return InstanceType.LoopCardinality; } else if (lc.getLoopCardinality()==null) { if (lc.getLoopDataInputRef()==null && lc.getInputDataItem()==null) return InstanceType.None; return InstanceType.DataInput; } } else if (isEnabled("loopCardinality")) { //$NON-NLS-1$ return InstanceType.LoopCardinality; } else if (isEnabled("loopDataInputRef")) { //$NON-NLS-1$ return InstanceType.DataInput; } return InstanceType.None; } private boolean isEnabled(String featureName) { final EClass eclass = PACKAGE.getMultiInstanceLoopCharacteristics(); EStructuralFeature feature = eclass.getEStructuralFeature(featureName); return super.isModelObjectEnabled(eclass,feature); } private void showCompletionConditionWidgets(boolean show) { if (!isEnabled("completionCondition")) //$NON-NLS-1$ return; if (show != completionConditionWidgetsShowing) { if (show) { completionConditionWidgets.setVisible(true); ((GridData)completionConditionWidgets.getLayoutData()).exclude = false; this.bindReference(completionConditionWidgets, getBO(), "completionCondition"); //$NON-NLS-1$ } else { completionConditionWidgets.setVisible(false); ((GridData)completionConditionWidgets.getLayoutData()).exclude = true; // remove the Transformation and assignments if (!updatingWidgets && getBO().getCompletionCondition()!=null) { editingDomain.getCommandStack().execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { getBusinessObjectDelegate().setValue(getBO(), Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_CompletionCondition(), null); } }); } } completionConditionWidgetsShowing = show; } } private void showLoopDataInputWidgets(boolean show) { if (!isEnabled("loopDataInputRef")) //$NON-NLS-1$ return; if (show != loopDataInputWidgetsShowing) { if (show) { instanceWidgets.setVisible(true); ((GridData)instanceWidgets.getLayoutData()).exclude = false; loopDataInputWidgets.setVisible(true); ((GridData)loopDataInputWidgets.getLayoutData()).exclude = false; this.bindReference(loopDataInputWidgets, getBO(), "loopDataInputRef"); //$NON-NLS-1$ } else { instanceWidgets.setVisible(false); ((GridData)instanceWidgets.getLayoutData()).exclude = true; loopDataInputWidgets.setVisible(false); ((GridData)loopDataInputWidgets.getLayoutData()).exclude = true; // remove the loopDataInputRef reference if (!updatingWidgets && getBO().getLoopDataInputRef()!=null) { editingDomain.getCommandStack().execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { getBusinessObjectDelegate().setValue(getBO(), Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_InputDataItem(), null); getBusinessObjectDelegate().setValue(getBO(), Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_LoopDataInputRef(), null); } }); } } loopDataInputWidgetsShowing = show; } } private void showLoopCardinalityWidgets(boolean show) { if (!isEnabled("loopCardinality")) //$NON-NLS-1$ return; if (show != loopCardinalityWidgetsShowing) { if (show) { instanceWidgets.setVisible(true); ((GridData)instanceWidgets.getLayoutData()).exclude = false; loopCardinalityWidgets.setVisible(true); ((GridData)loopCardinalityWidgets.getLayoutData()).exclude = false; this.bindReference(loopCardinalityWidgets, getBO(), "loopCardinality"); //$NON-NLS-1$ } else { instanceWidgets.setVisible(false); ((GridData)instanceWidgets.getLayoutData()).exclude = true; loopCardinalityWidgets.setVisible(false); ((GridData)loopCardinalityWidgets.getLayoutData()).exclude = true; // remove the Transformation and assignments if (!updatingWidgets && getBO().getLoopCardinality()!=null) { editingDomain.getCommandStack().execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { getBusinessObjectDelegate().setValue(getBO(), Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_LoopCardinality(), null); } }); } } loopCardinalityWidgetsShowing = show; } } private void showLoopDataOutputWidgets(boolean show) { if (!isEnabled("loopDataOutputRef")) //$NON-NLS-1$ return; if (show != loopDataOutputWidgetsShowing) { if (show) { loopDataOutputWidgets.setVisible(true); ((GridData)loopDataOutputWidgets.getLayoutData()).exclude = false; this.bindReference(loopDataOutputWidgets, getBO(), "loopDataOutputRef"); //$NON-NLS-1$ } else { loopDataOutputWidgets.setVisible(false); ((GridData)loopDataOutputWidgets.getLayoutData()).exclude = true; // remove the Loop Data Output and Output Data Item if (!updatingWidgets && (getBO().getLoopDataOutputRef()!=null || getBO().getOutputDataItem()!=null)) { editingDomain.getCommandStack().execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { getBusinessObjectDelegate().setValue(getBO(), Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_OutputDataItem(), null); getBusinessObjectDelegate().setValue(getBO(), Bpmn2Package.eINSTANCE.getMultiInstanceLoopCharacteristics_LoopDataOutputRef(), null); } }); } } loopDataOutputWidgetsShowing = show; } } protected void bindAttribute(Composite parent, EObject object, EAttribute attribute, String label) { if (attribute.getName().equals("behavior")) { //$NON-NLS-1$ throwBehaviorEditor = new ComboObjectEditor(this,object,attribute) { @Override public boolean setValue(Object result) { MultiInstanceLoopCharacteristics lc = (MultiInstanceLoopCharacteristics)object; boolean updated = super.setValue(result); if (updated) { switch (lc.getBehavior()) { case ALL: if (noneBehaviorEventEditor!=null) { noneBehaviorEventEditor.setVisible(false); } if (oneBehaviorEventEditor!=null) { oneBehaviorEventEditor.setVisible(false); } if (complexBehaviorList!=null) { complexBehaviorList.setVisible(false); } break; case NONE: if (oneBehaviorEventEditor!=null) { oneBehaviorEventEditor.setVisible(false); } if (complexBehaviorList!=null) { complexBehaviorList.setVisible(false); } if (noneBehaviorEventEditor!=null) { noneBehaviorEventEditor.setVisible(true); } break; case ONE: if (noneBehaviorEventEditor!=null) { noneBehaviorEventEditor.setVisible(false); } if (complexBehaviorList!=null) { complexBehaviorList.setVisible(false); } if (oneBehaviorEventEditor!=null) { oneBehaviorEventEditor.setVisible(true); } break; case COMPLEX: if (noneBehaviorEventEditor!=null) { noneBehaviorEventEditor.setVisible(false); } if (oneBehaviorEventEditor!=null) { oneBehaviorEventEditor.setVisible(false); } if (complexBehaviorList!=null) { complexBehaviorList.setVisible(true); } break; } redrawPage(); } return updated; } }; throwBehaviorEditor.createControl(parent,label); } else super.bindAttribute(parent, object, attribute, label); } protected void bindReference(Composite parent, final EObject object, final EReference reference) { final MultiInstanceLoopCharacteristics lc = (MultiInstanceLoopCharacteristics)object; TargetRuntime rt = TargetRuntime.getRuntime(object); if (reference == PACKAGE.getMultiInstanceLoopCharacteristics_CompletionCondition()) { if (isModelObjectEnabled(lc.eClass(), reference)) { // use a FormalExpression detail composite here if (completionConditionEditor==null) { completionConditionEditor = PropertiesCompositeFactory.INSTANCE.createDetailComposite( Expression.class, completionConditionWidgets, rt, SWT.BORDER); ((DefaultDetailComposite)completionConditionEditor).setPropertiesProvider( new AbstractPropertiesProvider(getBO()) { String[] properties = new String[] { "language", //$NON-NLS-1$ "body", //$NON-NLS-1$ // this must evaluate to a Boolean data type }; @Override public String[] getProperties() { return properties; } }); } // create a new Loop Cardinality FormalExpression if necessary Expression expression = getBO().getCompletionCondition(); if (expression==null) { expression = createModelObject(FormalExpression.class); InsertionAdapter.add(getBO(), PACKAGE.getMultiInstanceLoopCharacteristics_CompletionCondition(), expression); } completionConditionEditor.setBusinessObject(expression); completionConditionEditor.setTitle(Messages.MultiInstanceLoopCharacteristicsDetailComposite_Completion_Condition_Label); } } else if (reference == PACKAGE.getMultiInstanceLoopCharacteristics_LoopDataInputRef()) { if (isModelObjectEnabled(lc.eClass(), reference)) { if (loopDataInputEditor==null) { loopDataInputEditor = new DefaultDetailComposite(parent, SWT.BORDER) { @Override public void createBindings(EObject be) { ObjectEditor editor = new ComboObjectEditor(this,object,reference, PACKAGE.getDataInput()) { @Override protected boolean canCreateNew() { return false; } @Override protected Hashtable<String, Object> getChoiceOfValues(EObject object, EStructuralFeature feature) { Hashtable<String, Object> choices = super.getChoiceOfValues(object, feature); // remove the loop instance parameter from the loop collections list Activity activity = (Activity) lc.eContainer(); ItemAwareElement input = null; for (DataInputAssociation dia : activity.getDataInputAssociations()) { if (dia.getSourceRef().size()>0 && dia.getSourceRef().get(0)==lc.getInputDataItem()) { input = dia.getTargetRef(); break; } } for (Entry<String, Object> e : choices.entrySet()) { if (e.getValue()==input) { choices.remove(e.getKey()); break; } } return choices; } }; editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Input_Data_Label); if (be.eContainer() instanceof SubProcess) { editor = new LoopDataItemObjectEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem()); } else { // must be a Task editor = new LoopDataItemSelectionEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_InputDataItem()); } editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Input_Parameter_Label); } }; } loopDataInputEditor.setBusinessObject(object); loopDataInputEditor.setTitle(Messages.MultiInstanceLoopCharacteristicsDetailComposite_Input_Data_Title); } } else if (reference == PACKAGE.getMultiInstanceLoopCharacteristics_LoopDataOutputRef()) { if (isModelObjectEnabled(lc.eClass(), reference)) { if (loopDataOutputEditor==null) { loopDataOutputEditor = new DefaultDetailComposite(parent, SWT.BORDER) { @Override public void createBindings(EObject be) { ObjectEditor editor = new ComboObjectEditor(this,object,reference){ @Override protected boolean canCreateNew() { return false; } @Override protected Hashtable<String, Object> getChoiceOfValues(EObject object, EStructuralFeature feature) { Hashtable<String, Object> choices = super.getChoiceOfValues(object, feature); // remove the loop instance parameter from the loop collections list Activity activity = (Activity) lc.eContainer(); ItemAwareElement output = null; for (DataOutputAssociation doa : activity.getDataOutputAssociations()) { if (doa.getSourceRef().size()>0 && doa.getTargetRef()==lc.getOutputDataItem()) { output = doa.getSourceRef().get(0); break; } } for (Entry<String, Object> e : choices.entrySet()) { if (e.getValue()==output) { choices.remove(e.getKey()); break; } } return choices; } }; editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Output_Data_Label); if (be.eContainer() instanceof SubProcess) { editor = new LoopDataItemObjectEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem()); } else { // must be a Task editor = new LoopDataItemSelectionEditor(this, lc, PACKAGE.getMultiInstanceLoopCharacteristics_OutputDataItem()); } editor.createControl(getAttributesParent(), Messages.MultiInstanceLoopCharacteristicsDetailComposite_Output_Parameter_Label); } }; } loopDataOutputEditor.setBusinessObject(object); loopDataOutputEditor.setTitle(Messages.MultiInstanceLoopCharacteristicsDetailComposite_Output_Data_Title); } } else if (reference == PACKAGE.getMultiInstanceLoopCharacteristics_LoopCardinality()) { if (isModelObjectEnabled(lc.eClass(), reference)) { // use a FormalExpression detail composite here if (loopCardinalityEditor==null) { loopCardinalityEditor = PropertiesCompositeFactory.INSTANCE.createDetailComposite( Expression.class, loopCardinalityWidgets, rt, SWT.BORDER); } // create a new Loop Cardinality FormalExpression if necessary Expression expression = getBO().getLoopCardinality(); if (expression==null) { expression = createModelObject(FormalExpression.class); InsertionAdapter.add(getBO(), PACKAGE.getMultiInstanceLoopCharacteristics_LoopCardinality(), expression); } loopCardinalityEditor.setBusinessObject(expression); loopCardinalityEditor.setTitle(Messages.MultiInstanceLoopCharacteristicsDetailComposite_Expression_Title); } } else if (reference == PACKAGE.getMultiInstanceLoopCharacteristics_NoneBehaviorEventRef()) { if (isModelObjectEnabled(lc.eClass(), reference)) { String displayName = ExtendedPropertiesProvider.getLabel(object, reference); noneBehaviorEventEditor = new ComboObjectEditor(this,object,reference); noneBehaviorEventEditor.setStyle(SWT.READ_ONLY); noneBehaviorEventEditor.createControl(parent,displayName); noneBehaviorEventEditor.setVisible( lc.getBehavior() == MultiInstanceBehavior.NONE ); } } else if (reference == PACKAGE.getMultiInstanceLoopCharacteristics_OneBehaviorEventRef()) { if (isModelObjectEnabled(lc.eClass(), reference)) { String displayName = ExtendedPropertiesProvider.getLabel(object, reference); oneBehaviorEventEditor = new ComboObjectEditor(this,object,reference); oneBehaviorEventEditor.setStyle(SWT.READ_ONLY); oneBehaviorEventEditor.createControl(parent,displayName); oneBehaviorEventEditor.setVisible( lc.getBehavior() == MultiInstanceBehavior.ONE ); } } else super.bindReference(parent, object, reference); } protected AbstractListComposite bindList(EObject object, EStructuralFeature feature, EClass listItemClass) { MultiInstanceLoopCharacteristics lc = (MultiInstanceLoopCharacteristics)object; if (feature.getName().equals("complexBehaviorDefinition")) { //$NON-NLS-1$ if (isModelObjectEnabled(lc.eClass(), feature)) { complexBehaviorList = super.bindList(getAttributesParent(), object, feature, listItemClass); complexBehaviorList.setVisible( lc.getBehavior() == MultiInstanceBehavior.COMPLEX ); return complexBehaviorList; } return null; } else return super.bindList(object, feature, listItemClass); } public class DataInputOutputItemDialog extends FeatureEditingDialog { public DataInputOutputItemDialog(DiagramEditor editor, EObject object, EStructuralFeature feature) { super(editor, object, feature); } public DataInputOutputItemDialog(DiagramEditor editor, EObject object, EStructuralFeature feature, EObject value) { super(editor, object, feature, value); } protected Composite createDialogContent(Composite parent) { Composite content = new DefaultDetailComposite(parent, SWT.NONE) { @Override public AbstractPropertiesProvider getPropertiesProvider(EObject object) { if (propertiesProvider==null) { propertiesProvider = new AbstractPropertiesProvider(object) { String[] properties = new String[] { "anyAttribute", //$NON-NLS-1$ "name", //$NON-NLS-1$ "itemSubjectRef", //$NON-NLS-1$ }; @Override public String[] getProperties() { return properties; } }; } return propertiesProvider; } }; return content; } } 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(), element, Bpmn2Package.eINSTANCE.getItemAwareElement_ItemSubjectRef(), element); if ( dialog.open() == Window.OK) { this.updateText(); } } @Override protected String getText() { 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); } } }