private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput)

package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));
        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());
        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

{
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


{
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));
        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());
        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e)

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));

package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {

        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());
        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());

package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));

        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));
        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));
        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());
        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract

        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


@Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }

package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */

    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));
        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());
        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {
                if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }
            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}


if (refactorOperation.canExecute()) {
                    progressService.run(true, true, refactorOperation);
                }

package org.bonitasoft.studio.contract.ui.property.input;

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newHashSet;
import static org.bonitasoft.studio.common.emf.tools.ModelHelper.getAllElementOfTypeIn;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.bonitasoft.studio.common.NamingUtils;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.jface.BonitaErrorDialog;
import org.bonitasoft.studio.common.jface.FileActionDialog;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.contract.core.refactoring.RefactorContractInputOperation;
import org.bonitasoft.studio.contract.i18n.Messages;
import org.bonitasoft.studio.contract.ui.property.IViewerController;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractConstraint;
import org.bonitasoft.studio.model.process.ContractContainer;
import org.bonitasoft.studio.model.process.ContractInput;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.refactoring.core.RefactoringOperationType;
import org.bonitasoft.studio.refactoring.core.script.GroovyScriptRefactoringOperationFactory;
import org.bonitasoft.studio.refactoring.core.script.IScriptRefactoringOperationFactory;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.IProgressService;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

/**
 * @author Romain Bioteau
 */
public class ContractInputController implements IViewerController {

    private static final int NAME_COLUMN_INDEX = 0;

    private final IProgressService progressService;

    class EditNameRunnable implements Runnable {

        private final ColumnViewer viewer;

        private final ContractInput input;

        public EditNameRunnable(final ColumnViewer viewer, final ContractInput input) {
            this.viewer = viewer;
            this.input = input;
        }

        /*
         * (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        @Override
        public void run() {
            if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()) {
                viewer.setSelection(new StructuredSelection(input), false);
                final Widget item = viewer.testFindItem(input);
                if (item != null && !item.isDisposed()) {
                    viewer.reveal(input);
                    viewer.editElement(input, NAME_COLUMN_INDEX);
                }
            }
        }
    }

    public ContractInputController(final IProgressService progressService) {
        this.progressService = progressService;
    }

    @Override
    public ContractInput add(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final Contract contract = (Contract) contractObservable.getValue();
        final ContractInput defaultInput = createDefaultInput(contract);
        final EObject targetContainer = targetContainer(parentInput, contract);
        CustomEMFEditObservables.observeList(targetContainer, inputContainerFeature(targetContainer)).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private EObject targetContainer(final ContractInput parentInput, final Contract contract) {
        return parentInput != null ? parentInput.eContainer() : contract;
    }

    public ContractInput addChildInput(final ColumnViewer viewer) {
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (selection.isEmpty()) {
            return null;
        }
        final ContractInput parentInput = (ContractInput) selection.getFirstElement();
        final ContractInput defaultInput = createDefaultInput(ModelHelper.getFirstContainerOfType(parentInput, Contract.class));
        CustomEMFEditObservables.observeList(parentInput, ProcessPackage.Literals.CONTRACT_INPUT__INPUTS).add(defaultInput);
        viewer.getControl().getDisplay().asyncExec(new EditNameRunnable(viewer, defaultInput));
        return defaultInput;
    }

    private ContractInput createDefaultInput(final Contract contract) {
        final ContractInput contractInput = ProcessFactory.eINSTANCE.createContractInput();
        contractInput.setName(defaultContractInputName(contract));
        contractInput.setType(ContractInputType.TEXT);
        contractInput.setMapping(ProcessFactory.eINSTANCE.createContractInputMapping());
        return contractInput;
    }

    private String defaultContractInputName(final Contract contract) {
        return NamingUtils.generateNewName(newHashSet(transform(getAllElementOfTypeIn(contract, ContractInput.class), toInputName())), "input", 1);
    }

    private Function<ContractInput, String> toInputName() {
        return new Function<ContractInput, String>() {

            @Override
            public String apply(final ContractInput input) {
                return input.getName();
            }
        };
    }

    @Override
    public void remove(final ColumnViewer viewer) {
        final IObservableValue contractObservable = (IObservableValue) viewer.getInput();
        final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        final List<?> selectedInput = selection.toList();
        Contract contract = (Contract) contractObservable.getValue();
        if (openConfirmation(selectedInput)) {
            final RefactorContractInputOperation refactorOperation = newRefactorOperation(contract);
            final TransactionalEditingDomain editingDomain = editingDomain(contract);
            refactorOperation.setEditingDomain(editingDomain);
            refactorOperation.setAskConfirmation(shouldAskConfirmation());
            final CompoundCommand compoundCommand = refactorOperation.getCompoundCommand();
            for (final Object input : selectedInput) {
                final ContractInput contractInput = (ContractInput) input;
                contract = ModelHelper.getFirstContainerOfType(contractInput, Contract.class);
                // Parent input has been removed in current selection
                if (contract == null) {
                    continue;
                }
                refactorOperation.addItemToRefactor(null, contractInput);
                compoundCommand.append(DeleteCommand.create(editingDomain, contractInput));
                final Collection<ContractConstraint> constraintsReferencingInput = constraintsReferencingSingleInput(contract, contractInput);
                if (!constraintsReferencingInput.isEmpty()) {
                    compoundCommand.append(DeleteCommand.create(editingDomain, constraintsReferencingInput));
                }
            }
            try {

            } catch (final InvocationTargetException | InterruptedException e) {
                BonitaStudioLog.error("Failed to remove contract input.", e);
                openErrorDialog(e);
            }
        }
    }

    protected boolean shouldAskConfirmation() {
        return true;
    }

    private Collection<ContractConstraint> constraintsReferencingSingleInput(final Contract contract, final ContractInput contractInput) {
        return newHashSet(filter(contract.getConstraints(), havingInputReference(contractInput.getName())));
    }

    private Predicate<ContractConstraint> havingInputReference(final String inputName) {
        return new Predicate<ContractConstraint>() {

            @Override
            public boolean apply(final ContractConstraint constraint) {
                return constraint.getInputNames().contains(inputName) && constraint.getInputNames().size() == 1;
            }
        };
    }

    protected TransactionalEditingDomain editingDomain(final Contract contract) {
        return TransactionUtil.getEditingDomain(contract);
    }

    protected RefactorContractInputOperation newRefactorOperation(final Contract contract) {
        return new RefactorContractInputOperation(ModelHelper.getFirstContainerOfType(contract, ContractContainer.class), scriptRefactoringOperationFactory(), RefactoringOperationType.REMOVE);
    }

    protected IScriptRefactoringOperationFactory scriptRefactoringOperationFactory() {
        return new GroovyScriptRefactoringOperationFactory();
    }

    private EReference inputContainerFeature(final EObject eContainer) {
        return eContainer instanceof ContractInput ? ProcessPackage.Literals.CONTRACT_INPUT__INPUTS : ProcessPackage.Literals.CONTRACT__INPUTS;
    }

    protected void openErrorDialog(final Throwable e) {
        if (!FileActionDialog.getDisablePopup()) {
            new BonitaErrorDialog(Display.getDefault().getActiveShell(), Messages.removeInputErrorTitle, Messages.removeInputErrorMsg, e).open();
        }
    }

    protected boolean openConfirmation(final List<?> selectedInput) {
        final StringBuilder message = new StringBuilder(Messages.removeInputConfirmationMessagePart1);
        for (final Object input : selectedInput) {
            message.append(SWT.CR);
            message.append("- " + ((ContractInput) input).getName());
            message.append(SWT.CR);
            message.append(Messages.removeInputConfirmationMessagesPart2);
        }
        return FileActionDialog.getDisablePopup() ? true : MessageDialog.openConfirm(Display.getDefault().getActiveShell(), Messages.removeInputConfirmationTitle, message.toString());
    }

    @Override
    public void moveUp(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }

    @Override
    public void moveDown(final ColumnViewer viewer) {
        throw new UnsupportedOperationException("Not implemented yet.");
    }
}