content: /*******************************************************************************
   * Copyright (c) 2000, 2009 IBM Corporation and others.
   * All rights reserved. This program and the accompanying materials
   * are 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:
   *   Martin Moebius (m.moebius@gmx.de) - initial API and implementation
   *             (report 28793)
   *   IBM Corporation - updates
   *******************************************************************************/
  
  package org.eclipse.wst.jsdt.ui.actions;
  
  import java.lang.reflect.InvocationTargetException;
  import java.util.ArrayList;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IStatus;
  import org.eclipse.jface.dialogs.MessageDialog;
  import org.eclipse.jface.operation.IRunnableContext;
  import org.eclipse.jface.text.IRewriteTarget;
  import org.eclipse.jface.text.ITextSelection;
  import org.eclipse.jface.viewers.ILabelProvider;
  import org.eclipse.jface.viewers.IStructuredSelection;
  import org.eclipse.jface.viewers.ITreeContentProvider;
  import org.eclipse.jface.viewers.Viewer;
  import org.eclipse.jface.viewers.ViewerComparator;
  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.graphics.Image;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Link;
  import org.eclipse.swt.widgets.Shell;
  import org.eclipse.ui.IEditorPart;
  import org.eclipse.ui.IWorkbenchSite;
  import org.eclipse.ui.PlatformUI;
  import org.eclipse.ui.dialogs.ISelectionStatusValidator;
  import org.eclipse.wst.jsdt.core.IField;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
  import org.eclipse.wst.jsdt.core.IType;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  import org.eclipse.wst.jsdt.core.Signature;
  import org.eclipse.wst.jsdt.core.dom.AST;
  import org.eclipse.wst.jsdt.core.dom.IBinding;
  import org.eclipse.wst.jsdt.core.dom.IFunctionBinding;
  import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
  import org.eclipse.wst.jsdt.core.dom.IVariableBinding;
  import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
  import org.eclipse.wst.jsdt.core.dom.VariableDeclarationFragment;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.AddDelegateMethodsOperation;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.CodeGenerationSettings;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.StubUtility2;
  import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
  import org.eclipse.wst.jsdt.internal.corext.dom.Bindings;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.util.JavaElementUtil;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.util.RefactoringASTParser;
  import org.eclipse.wst.jsdt.internal.corext.template.java.CodeTemplateContextType;
  import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil;
  import org.eclipse.wst.jsdt.internal.corext.util.Messages;
  import org.eclipse.wst.jsdt.internal.ui.IJavaHelpContextIds;
  import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
  import org.eclipse.wst.jsdt.internal.ui.actions.ActionMessages;
  import org.eclipse.wst.jsdt.internal.ui.actions.ActionUtil;
  import org.eclipse.wst.jsdt.internal.ui.actions.SelectionConverter;
  import org.eclipse.wst.jsdt.internal.ui.actions.WorkbenchRunnableAdapter;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.SourceActionDialog;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.StatusInfo;
  import org.eclipse.wst.jsdt.internal.ui.javaeditor.CompilationUnitEditor;
  import org.eclipse.wst.jsdt.internal.ui.preferences.JavaPreferencesSettings;
  import org.eclipse.wst.jsdt.internal.ui.util.BusyIndicatorRunnableContext;
  import org.eclipse.wst.jsdt.internal.ui.util.ElementValidator;
  import org.eclipse.wst.jsdt.internal.ui.util.ExceptionHandler;
  import org.eclipse.wst.jsdt.internal.ui.viewsupport.BindingLabelProvider;
  import org.eclipse.wst.jsdt.ui.JavaScriptUI;
  
  import com.ibm.icu.text.Collator;
  
  /**
   * Creates delegate methods for a type's fields. Opens a dialog with a list of fields for
   * which delegate methods can be generated. User is able to check or uncheck items before
   * methods are generated.
   * <p>
   * Will open the parent compilation unit in a JavaScript editor. The result is unsaved, so the
   * user can decide if the changes are acceptable.
   * <p>
   * The action is applicable to structured selections containing elements of type
   * <code>IField</code> or <code>IType</code>.
   * 
   * <p>
   * This class may be instantiated; it is not intended to be subclassed.
   * </p>
   * 
   * Provisional API: This class/interface is part of an interim API that is still under development and expected to
   * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
   * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
   * (repeatedly) as the API evolves.
   */
  public class AddDelegateMethodsAction extends SelectionDispatchAction {
  
  	// ---- Helpers -------------------------------------------------------------------
  
  	private static class AddDelegateMethodsActionStatusValidator implements ISelectionStatusValidator {
  
  		private static int fEntries;
  
  		AddDelegateMethodsActionStatusValidator(int entries) {
  			fEntries= entries;
  		}
  
  		public IStatus validate(Object[] selection) {
  			StatusInfo info= new StatusInfo();
  			if (selection != null && selection.length > 0) {
  				int count= 0;
  				List bindings= new ArrayList(selection.length);
  				IFunctionBinding binding= null;
  				for (int index= 0; index < selection.length; index++) {
  					if (selection[index] instanceof IBinding[]) {
  						count++;
  						binding= (IFunctionBinding) ((IBinding[]) selection[index])[1];
  						IFunctionBinding existing= null;
  						for (int offset= 0; offset < bindings.size(); offset++) {
  							existing= (IFunctionBinding) bindings.get(offset);
  							if (Bindings.isEqualMethod(binding, existing.getName(), existing.getParameterTypes())) {
  								return new StatusInfo(IStatus.ERROR, ActionMessages.AddDelegateMethodsAction_duplicate_methods); 
  							}
  						}
  						bindings.add(binding);
  						info= new StatusInfo(IStatus.INFO, Messages.format(ActionMessages.AddDelegateMethodsAction_selectioninfo_more, new Object[] { String.valueOf(count), String.valueOf(fEntries)})); 
  					}
  				}
  			}
  			return info;
  		}
  	}
  
  	private static class AddDelegateMethodsContentProvider implements ITreeContentProvider {
  
  		private IBinding[][] fBindings= new IBinding[0][0];
  
  		private int fCount= 0;
  
  		private IVariableBinding[] fExpanded= new IVariableBinding[0];
  
  		private final JavaScriptUnit fUnit;
  
  		AddDelegateMethodsContentProvider(IType type, IField[] fields) throws JavaScriptModelException {
  			RefactoringASTParser parser= new RefactoringASTParser(AST.JLS3);
  			fUnit= parser.parse(type.getJavaScriptUnit(), true);
  			final ITypeBinding binding= ASTNodes.getTypeBinding(fUnit, type);
  			if (binding != null) {
  				IBinding[][] bindings= StubUtility2.getDelegatableMethods(fUnit.getAST(), binding);
  				if (bindings != null) {
  					fBindings= bindings;
  					fCount= bindings.length;
  				}
  				List expanded= new ArrayList();
  				for (int index= 0; index < fields.length; index++) {
  					VariableDeclarationFragment fragment= ASTNodeSearchUtil.getFieldDeclarationFragmentNode(fields[index], fUnit);
  					if (fragment != null) {
  						IVariableBinding variableBinding= fragment.resolveBinding();
  						if (variableBinding != null)
  							expanded.add(variableBinding);
  					}
  				}
  				IVariableBinding[] result= new IVariableBinding[expanded.size()];
  				expanded.toArray(result);
  				fExpanded= result;
  			}
  		}
  
  		public JavaScriptUnit getCompilationUnit() {
  			return fUnit;
  		}
  
  		public void dispose() {
  		}
  
  		public Object[] getChildren(Object element) {
  			if (element instanceof IVariableBinding) {
  				IVariableBinding binding= (IVariableBinding) element;
  				List result= new ArrayList();
  				final String key= binding.getKey();
  				for (int index= 0; index < fBindings.length; index++)
  					if (fBindings[index][0].getKey().equals(key))
  						result.add(fBindings[index]);
  				return result.toArray();
  			}
  			return null;
  		}
  
  		public int getCount() {
  			return fCount;
  		}
  
  		public Object[] getElements(Object inputElement) {
  			Set keys= new HashSet();
  			List result= new ArrayList();
  			for (int index= 0; index < fBindings.length; index++) {
  				IBinding[] bindings= fBindings[index];
  				final String key= bindings[0].getKey();
  				if (!keys.contains(key)) {
  					keys.add(key);
  					result.add(bindings[0]);
  				}
  			}
  			return result.toArray();
  		}
  
  		public IVariableBinding[] getExpandedElements() {
  			return fExpanded;
  		}
  
  		public IBinding[][] getInitiallySelectedElements() {
  			List result= new ArrayList();
  			for (int index= 0; index < fBindings.length; index++)
  				for (int offset= 0; offset < fExpanded.length; offset++)
  					if (fExpanded[offset].getKey().equals(fBindings[index][0].getKey()))
  						result.add(fBindings[index]);
  			return (IBinding[][]) result.toArray(new IBinding[result.size()][2]);
  		}
  
  		public Object getParent(Object element) {
  			if (element instanceof IBinding[])
  				return ((IBinding[]) element)[0];
  			return null;
  		}
  
  		public boolean hasChildren(Object element) {
  			return element instanceof IVariableBinding;
  		}
  
  		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
  		}
  	}
  
  	private static class AddDelegateMethodsDialog extends SourceActionDialog {
  
  		public AddDelegateMethodsDialog(Shell parent, ILabelProvider labelProvider, ITreeContentProvider contentProvider, CompilationUnitEditor editor, IType type, boolean isConstructor) throws JavaScriptModelException {
  			super(parent, labelProvider, contentProvider, editor, type, isConstructor);
  		}
  
  		protected void configureShell(Shell shell) {
  			super.configureShell(shell);
  			PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, IJavaHelpContextIds.ADD_DELEGATE_METHODS_SELECTION_DIALOG);
  		}
  		
  		/*
  		 * @see org.eclipse.wst.jsdt.internal.ui.dialogs.SourceActionDialog#createLinkControl(org.eclipse.swt.widgets.Composite)
  		 */
  		protected Control createLinkControl(Composite composite) {
  			Link link= new Link(composite, SWT.WRAP);
  			link.setText(ActionMessages.AddDelegateMethodsAction_template_link_message); 
  			link.addSelectionListener(new SelectionAdapter() {
  				public void widgetSelected(SelectionEvent e) {
  					openCodeTempatePage(CodeTemplateContextType.OVERRIDECOMMENT_ID);
  				}
  			});
  			link.setToolTipText(ActionMessages.AddDelegateMethodsAction_template_link_tooltip); 
  			
  			GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
  			gridData.widthHint= convertWidthInCharsToPixels(40); // only expand further if anyone else requires it
  			link.setLayoutData(gridData);
  			return link;
  		}
  	}
  
  	private static class AddDelegateMethodsLabelProvider extends BindingLabelProvider {
  
  		public Image getImage(Object element) {
  			if (element instanceof IBinding[]) {
  				return super.getImage((((IBinding[]) element)[1]));
  			} else if (element instanceof IVariableBinding) {
  				return super.getImage(element);
  			}
  			return null;
  		}
  
  		public String getText(Object element) {
  			if (element instanceof IBinding[]) {
  				return super.getText((((IBinding[]) element)[1]));
  			} else if (element instanceof IVariableBinding) {
  				return super.getText(element);
  			}
  			return null;
  		}
  	}
  
  	private static class AddDelegateMethodsViewerComparator extends ViewerComparator {
  
  		private final BindingLabelProvider fProvider= new BindingLabelProvider();
  		private final Collator fCollator= Collator.getInstance();
  
  		public int category(Object element) {
  			if (element instanceof IBinding[])
  				return 0;
  			return 1;
  		}
  
  		public int compare(Viewer viewer, Object object1, Object object2) {
  			String first= ""; //$NON-NLS-1$
  			String second= ""; //$NON-NLS-1$
  			if (object1 instanceof IBinding[])
  				first= fProvider.getText(((IBinding[]) object1)[1]);
  			else if (object1 instanceof IVariableBinding)
  				first= ((IBinding) object1).getName();
  			if (object2 instanceof IBinding[])
  				second= fProvider.getText(((IBinding[]) object2)[1]);
  			else if (object2 instanceof IVariableBinding)
  				second= ((IBinding) object2).getName();
  			return fCollator.compare(first, second);
  		}
  	}
  
  	private static final String DIALOG_TITLE= ActionMessages.AddDelegateMethodsAction_error_title; 
  
  	private static boolean hasPrimitiveType(IField field) throws JavaScriptModelException {
  		String signature= field.getTypeSignature();
  		char first= Signature.getElementType(signature).charAt(0);
  		return (first != Signature.C_RESOLVED && first != Signature.C_UNRESOLVED);
  	}
  
  	private static boolean isArray(IField field) throws JavaScriptModelException {
  		return Signature.getArrayCount(field.getTypeSignature()) > 0;
  	}
  
  	private CompilationUnitEditor fEditor;
  
  	/**
  	 * Note: This constructor is for internal use only. Clients should not call this
  	 * constructor.
  	 * 
  	 * @param editor the compilation unit editor
  	 */
  	public AddDelegateMethodsAction(CompilationUnitEditor editor) {
  		this(editor.getEditorSite());
  		fEditor= editor;
  		setEnabled(SelectionConverter.getInputAsCompilationUnit(editor) != null);
  	}
  
  	/**
  	 * Creates a new <code>AddDelegateMethodsAction</code>. The action requires that
  	 * the selection provided by the site's selection provider is of type <code>
  	 * org.eclipse.jface.viewers.IStructuredSelection</code>.
  	 * 
  	 * @param site the site providing context information for this action
  	 */
  	public AddDelegateMethodsAction(IWorkbenchSite site) {
  		super(site);
  		setText(ActionMessages.AddDelegateMethodsAction_label); 
  		setDescription(ActionMessages.AddDelegateMethodsAction_description); 
  		setToolTipText(ActionMessages.AddDelegateMethodsAction_tooltip); 
  
  		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.ADD_DELEGATE_METHODS_ACTION);
  	}
  
  	private boolean canEnable(IStructuredSelection selection) throws JavaScriptModelException {
  		if (getSelectedFields(selection) != null)
  			return true;
  
  		if ((selection.size() == 1) && (selection.getFirstElement() instanceof IType)) {
  			IType type= (IType) selection.getFirstElement();
  			return type.getJavaScriptUnit() != null;
  		}
  
  		if ((selection.size() == 1) && (selection.getFirstElement() instanceof IJavaScriptUnit))
  			return true;
  
  		return false;
  	}
  
  	private boolean canRunOn(IField[] fields) throws JavaScriptModelException {
  		if (fields == null || fields.length == 0)
  			return false;
  		int count= 0;
  		for (int index= 0; index < fields.length; index++) {
  			if (!hasPrimitiveType(fields[index]) || isArray(fields[index]))
  				count++;
  		}
  		if (count == 0)
  			MessageDialog.openInformation(getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_not_applicable); 
  		return (count > 0);
  	}
  
  	private boolean canRunOn(IType type) throws JavaScriptModelException {
  		if (type == null || type.getJavaScriptUnit() == null) {
  			MessageDialog.openInformation(getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_not_in_source_file); 
  			return false;
  		}
  		return canRunOn(type.getFields());
  	}
  
  	private IField[] getSelectedFields(IStructuredSelection selection) {
  		List elements= selection.toList();
  		if (elements.size() > 0) {
  			IField[] result= new IField[elements.size()];
  			IJavaScriptUnit unit= null;
  			for (int index= 0; index < elements.size(); index++) {
  				if (elements.get(index) instanceof IField) {
  					IField field= (IField) elements.get(index);
  
  					if (index == 0) {
  						// remember the CU of the first element
  						unit= field.getJavaScriptUnit();
  						if (unit == null) {
  							return null;
  						}
  					} else if (!unit.equals(field.getJavaScriptUnit())) {
  						// all fields must be in the same CU
  						return null;
  					}
  
  					result[index]= field;
  				} else {
  					return null;
  				}
  			}
  			return result;
  		}
  		return null;
  	}
  
  	/*
  	 * (non-Javadoc) Method declared on SelectionDispatchAction
  	 */
  	public void run(IStructuredSelection selection) {
  		try {
  			IField[] selectedFields= getSelectedFields(selection);
  			if (canRunOn(selectedFields)) {
  				run(selectedFields[0].getDeclaringType(), selectedFields, false);
  				return;
  			}
  			Object firstElement= selection.getFirstElement();
  			if (firstElement instanceof IType)
  				run((IType) firstElement, new IField[0], false);
  			else if (firstElement instanceof IJavaScriptUnit)
  				run(JavaElementUtil.getMainType((IJavaScriptUnit) firstElement), new IField[0], false);
  			else if (!(firstElement instanceof IField))
  				MessageDialog.openInformation(getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_not_applicable); 
  		} catch (CoreException e) {
  			ExceptionHandler.handle(e, getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_error_actionfailed); 
  		}
  
  	}
  
  	/*
  	 * (non-Javadoc) Method declared on SelectionDispatchAction
  	 */
  	public void run(ITextSelection selection) {
  		try {
  			if (!ActionUtil.isProcessable(fEditor))
  				return;
  
  			IJavaScriptElement[] elements= SelectionConverter.codeResolveForked(fEditor, true);
  			if (elements.length == 1 && (elements[0] instanceof IField)) {
  				IField field= (IField) elements[0];
  				run(field.getDeclaringType(), new IField[] { field}, true);
  				return;
  			}
  			IJavaScriptElement element= SelectionConverter.getElementAtOffset(fEditor);
  			if (element != null) {
  				IType type= (IType) element.getAncestor(IJavaScriptElement.TYPE);
  				if (type != null) {
  					if (type.getFields().length > 0) {
  						run(type, new IField[0], true);
  						return;
  					}
  				}
  			}
  			MessageDialog.openInformation(getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_not_applicable); 
  		} catch (CoreException e) {
  			ExceptionHandler.handle(e, getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_error_actionfailed); 
  		} catch (InvocationTargetException e) {
  			ExceptionHandler.handle(e, getShell(), DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_error_actionfailed); 
  		} catch (InterruptedException e) {
  			// cancelled
  		}
  	}
  
  	private void run(IType type, IField[] preselected, boolean editor) throws CoreException {
  		if (!ElementValidator.check(type, getShell(), DIALOG_TITLE, editor))
  			return;
  		if (!ActionUtil.isEditable(fEditor, getShell(), type))
  			return;
  		if (!canRunOn(type))
  			return;
  		showUI(type, preselected);
  	}
  
  	// ---- Structured Viewer -----------------------------------------------------------
  
  	/*
  	 * (non-Javadoc) Method declared on SelectionDispatchAction
  	 */
  	public void selectionChanged(IStructuredSelection selection) {
  		try {
  			setEnabled(canEnable(selection));
  		} catch (JavaScriptModelException e) {
  			// http://bugs.eclipse.org/bugs/show_bug.cgi?id=19253
  			if (JavaModelUtil.isExceptionToBeLogged(e))
  				JavaScriptPlugin.log(e);
  			setEnabled(false);
  		}
  	}
  
  	// ---- JavaScript Editor --------------------------------------------------------------
  
  	/*
  	 * (non-Javadoc) Method declared on SelectionDispatchAction
  	 */
  	public void selectionChanged(ITextSelection selection) {
  	}
  
  	private void showUI(IType type, IField[] fields) {
  		try {
  			AddDelegateMethodsContentProvider provider= new AddDelegateMethodsContentProvider(type, fields);
  			SourceActionDialog dialog= new AddDelegateMethodsDialog(getShell(), new AddDelegateMethodsLabelProvider(), provider, fEditor, type, false);
  			dialog.setValidator(new AddDelegateMethodsActionStatusValidator(provider.getCount()));
  			AddDelegateMethodsViewerComparator comparator= new AddDelegateMethodsViewerComparator();
  			dialog.setComparator(comparator);
  			dialog.setInput(new Object());
  			dialog.setContainerMode(true);
  			dialog.setMessage(ActionMessages.AddDelegateMethodsAction_message); 
  			dialog.setTitle(ActionMessages.AddDelegateMethodsAction_title); 
  			IVariableBinding[] expanded= provider.getExpandedElements();
  			if (expanded.length > 0) {
  				dialog.setExpandedElements(expanded);
  			} else {
  				Object[] elements= provider.getElements(null);
  				if (elements.length > 0) {
  					comparator.sort(null, elements);
  					Object[] expand= { elements[0]};
  					dialog.setExpandedElements(expand);
  				}
  			}
  			dialog.setInitialSelections(provider.getInitiallySelectedElements());
  			dialog.setSize(60, 18);
  			int result= dialog.open();
  			if (result == Window.OK) {
  				Object[] object= dialog.getResult();
  				if (object == null) {
  					notifyResult(false);
  					return;
  				}
  				List tuples= new ArrayList(object.length);
  				for (int index= 0; index < object.length; index++) {
  					if (object[index] instanceof IBinding[])
  						tuples.add(object[index]);
  				}
  				IEditorPart part= JavaScriptUI.openInEditor(type);
  				IRewriteTarget target= (IRewriteTarget) part.getAdapter(IRewriteTarget.class);
  				try {
  					if (target != null)
  						target.beginCompoundChange();
  					CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaScriptProject());
  					settings.createComments= dialog.getGenerateComment();
  					final int size= tuples.size();
  					String[] methodKeys= new String[size];
  					String[] variableKeys= new String[size];
  					for (int index= 0; index < size; index++) {
  						final IBinding[] tuple= (IBinding[]) tuples.get(index);
  						variableKeys[index]= tuple[0].getKey();
  						methodKeys[index]= tuple[1].getKey();
  					}
  					AddDelegateMethodsOperation operation= new AddDelegateMethodsOperation(type, dialog.getElementPosition(), provider.getCompilationUnit(), variableKeys, methodKeys, settings, true, false);
  					IRunnableContext context= JavaScriptPlugin.getActiveWorkbenchWindow();
  					if (context == null)
  						context= new BusyIndicatorRunnableContext();
  					try {
  						PlatformUI.getWorkbench().getProgressService().runInUI(context, new WorkbenchRunnableAdapter(operation, operation.getSchedulingRule()), operation.getSchedulingRule());
  					} catch (InterruptedException exception) {
  						// User interruption
  					}
  				} finally {
  					if (target != null)
  						target.endCompoundChange();
  				}
  			}
  			notifyResult(result == Window.OK);
  		} catch (CoreException exception) {
  			ExceptionHandler.handle(exception, DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_error_actionfailed); 
  		} catch (InvocationTargetException e) {
  			ExceptionHandler.handle(e, DIALOG_TITLE, ActionMessages.AddDelegateMethodsAction_error_actionfailed); 
  		}
  	}
  }
  