blob: 73bdc9512ffefbb7f55cf609633c87d9a1838138 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Remy Chi Jian Suen 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:
* Remy Chi Jian Suen <remy.suen@gmail.com> - initial API and implementation
******************************************************************************/
package org.eclipse.ecf.remoteservices.ui;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.internal.remoteservices.ui.Messages;
import org.eclipse.ecf.remoteservices.ui.RemoteMethod.Parameter;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.jface.window.SameShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
/**
* The MethodInvocationDialog allows a user to select a method given a
* <code>java.lang.Class</code> to invoke and communicate with a remote service.
*
* @since 2.0
*/
public final class MethodInvocationDialog extends Dialog {
/**
* An integer constant that corresponds to the "Async Listener" selection.
*
* @see #getInvocationType()
*/
public static final int ASYNC_LISTENER = 0;
/**
* An integer constant that corresponds to the "Async Future Result"
* selection.
*
* @see #getInvocationType()
*/
public static final int ASYNC_FUTURE_RESULT = ASYNC_LISTENER + 1;
/**
* An integer constant that corresponds to the "Async Fire-and-Go"
* selection.
*
* @see #getInvocationType()
*/
public static final int ASYNC_FIRE_AND_GO = ASYNC_FUTURE_RESULT + 1;
/**
* An integer constant that corresponds to the "OSGi Service Proxy"
* selection.
*
* @see #getInvocationType()
*/
public static final int OSGI_SERVICE_PROXY = ASYNC_FIRE_AND_GO + 1;
/**
* An integer constant that corresponds to the "Remote Service Proxy"
* selection.
*
* @see #getInvocationType()
*/
public static final int REMOTE_SERVICE_PROXY = OSGI_SERVICE_PROXY + 1;
/**
* An integer constant that corresponds to the "Synchronous" selection.
*
* @see #getInvocationType()
*/
public static final int SYNCHRONOUS = REMOTE_SERVICE_PROXY + 1;
private static final String[] COLUMN_PROPERTIES = { "Parameter", "Argument" }; //$NON-NLS-1$ //$NON-NLS-2$
/**
* Provide a default timeout value of 30,000 milliseconds.
*/
private static final String DEFAULT_TIMEOUT_VALUE = "30000"; //$NON-NLS-1$
private TableViewer methodsViewer;
private TableViewer parametersViewer;
private Text timeoutText;
private Combo invocationCombo;
private final RemoteMethod[] methods;
private Method method;
private Object[] methodArguments;
private int timeout;
private int invocationType;
/**
* Creates a new MethodInvocationDialog on top of the specified shell
* provider.
*
* @param parentShell
* the provider to return the parent shell of this dialog
* @param cls
* the class to select the methods from
*/
public MethodInvocationDialog(IShellProvider parentShell, Class cls) {
super(parentShell);
Assert.isNotNull(cls);
Method[] methods = cls.getMethods();
final List validMethods = new ArrayList();
for (int i = 0; i < methods.length; i++) {
final Class[] parameters = methods[i].getParameterTypes();
final String[] types = new String[parameters.length];
if (types.length == 0) {
validMethods.add(methods[i]);
continue;
}
boolean match = true;
for (int j = 0; j < types.length; j++) {
final String name = parameters[j].getName();
if (!name.equals("char") && !name.equals("boolean") //$NON-NLS-1$ //$NON-NLS-2$
&& !name.equals("int") && !name.equals("double") //$NON-NLS-1$ //$NON-NLS-2$
&& !name.equals("float") && !name.equals("long") //$NON-NLS-1$ //$NON-NLS-2$
&& !name.equals("short") && !name.equals("byte") //$NON-NLS-1$ //$NON-NLS-2$
&& !name.equals("java.lang.String")) { //$NON-NLS-1$
match = false;
break;
}
}
if (match) {
validMethods.add(methods[i]);
}
}
methods = (Method[]) validMethods.toArray(new Method[validMethods
.size()]);
this.methods = new RemoteMethod[methods.length];
for (int i = 0; i < methods.length; i++) {
this.methods[i] = new RemoteMethod(methods[i]);
}
}
/**
* Creates a new MethodInvocationDialog over the provided shell.
*
* @param parentShell
* the parent shell
* @param cls
* the class to select the methods from
*/
public MethodInvocationDialog(Shell parentShell, Class cls) {
this(new SameShellProvider(parentShell), cls);
}
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.MethodInvocationDialog_ShellTitle);
}
protected Control createDialogArea(Composite parent) {
parent = (Composite) super.createDialogArea(parent);
final Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(new GridLayout(2, true));
Label label = new Label(composite, SWT.LEAD);
label.setText(Messages.MethodInvocationDialog_AvailableMethodsLabel);
label = new Label(composite, SWT.LEAD);
label.setText(Messages.MethodInvocationDialog_ArgumentsLabel);
methodsViewer = new TableViewer(composite, SWT.V_SCROLL | SWT.H_SCROLL
| SWT.BORDER);
methodsViewer.getControl().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
methodsViewer.setContentProvider(new ArrayContentProvider());
methodsViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent e) {
final IStructuredSelection iss = (IStructuredSelection) e
.getSelection();
final Object element = iss.getFirstElement();
if (element != null) {
getButton(IDialogConstants.OK_ID).setEnabled(
!timeoutText.getText().equals("")); //$NON-NLS-1$
final RemoteMethod method = (RemoteMethod) element;
parametersViewer.setInput(method.getParameters());
}
}
});
methodsViewer.setLabelProvider(new LabelProvider() {
public String getText(Object element) {
final RemoteMethod method = (RemoteMethod) element;
return method.getReturnType() + ' ' + method.getSignature();
}
});
parametersViewer = new TableViewer(composite, SWT.V_SCROLL
| SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.BORDER);
parametersViewer.getControl().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
parametersViewer.setContentProvider(new ArrayContentProvider());
parametersViewer.setLabelProvider(new ITableLabelProvider() {
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
final Parameter p = (Parameter) element;
if (columnIndex == 0) {
final String name = p.getParameter().getName();
if (name.charAt(0) == 'j') {
// this is java.lang.String
return "String"; //$NON-NLS-1$
} else {
return name;
}
} else {
return p.getArgument();
}
}
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return true;
}
public void removeListener(ILabelProviderListener listener) {
}
});
parametersViewer.setCellEditors(new CellEditor[] { null,
new TextCellEditor(parametersViewer.getTable()) });
parametersViewer.setCellModifier(new ICellModifier() {
public boolean canModify(Object element, String property) {
return property.equals(COLUMN_PROPERTIES[1]);
}
public Object getValue(Object element, String property) {
return ((Parameter) element).getArgument();
}
public void modify(Object element, String property, Object value) {
if (property.equals(COLUMN_PROPERTIES[1])) {
if (element instanceof TableItem) {
final TableItem item = ((TableItem) element);
final Parameter p = (Parameter) item.getData();
final String argument = (String) value;
p.setArgument(argument);
item.setText(1, argument);
}
}
}
});
parametersViewer.setColumnProperties(COLUMN_PROPERTIES);
final Table table = parametersViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableColumn column = new TableColumn(table, SWT.LEAD);
column.setWidth(150);
column.setText(Messages.MethodInvocationDialog_ParameterColumn);
column = new TableColumn(table, SWT.LEAD);
column.setWidth(150);
column.setText(Messages.MethodInvocationDialog_ValueColumn);
methodsViewer.setInput(methods);
final Composite bottomComposite = new Composite(composite, SWT.NONE);
bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false, 2, 1));
final GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 0;
layout.marginHeight = 0;
bottomComposite.setLayout(layout);
label = new Label(bottomComposite, SWT.LEAD);
label.setText(Messages.MethodInvocationDialog_TimeoutLabel);
label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));
timeoutText = new Text(bottomComposite, SWT.BORDER);
timeoutText.setText(DEFAULT_TIMEOUT_VALUE);
timeoutText.addVerifyListener(new VerifyListener() {
public void verifyText(VerifyEvent e) {
switch (e.text.length()) {
case 0:
e.doit = true;
break;
case 1:
e.doit = Character.isDigit(e.text.charAt(0));
break;
default:
e.doit = false;
break;
}
}
});
timeoutText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
getButton(IDialogConstants.OK_ID).setEnabled(
!timeoutText.getText().equals("") //$NON-NLS-1$
&& !methodsViewer.getSelection().isEmpty());
}
});
timeoutText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
false));
label = new Label(bottomComposite, SWT.LEAD);
label.setText(Messages.MethodInvocationDialog_InvocationTypeLabel);
label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));
invocationCombo = new Combo(bottomComposite, SWT.READ_ONLY);
invocationCombo
.setItems(new String[] {
Messages.MethodInvocationDialog_InvocationTypeAsyncListener,
Messages.MethodInvocationDialog_InvocationTypeAsyncFutureResult,
Messages.MethodInvocationDialog_InvocationTypeAsyncFireAndGo,
Messages.MethodInvocationDialog_InvocationTypeOSGiServiceProxy,
Messages.MethodInvocationDialog_InvocationTypeRemoteServiceProxy,
Messages.MethodInvocationDialog_InvocationTypeSynchronous });
invocationCombo.select(0);
bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false));
return parent;
}
public void create() {
super.create();
final Button okButton = getButton(IDialogConstants.OK_ID);
okButton.setEnabled(false);
okButton.setText(Messages.MethodInvocationDialog_BUTTON_INVOKE_TEXT);
}
protected void okPressed() {
final IStructuredSelection selection = (IStructuredSelection) methodsViewer
.getSelection();
final RemoteMethod remoteMethod = (RemoteMethod) selection
.getFirstElement();
method = remoteMethod.getMethod();
final Parameter[] p = remoteMethod.getParameters();
methodArguments = new Object[p.length];
for (int i = 0; i < p.length; i++) {
final String name = p[i].getParameter().getName();
final String arg = p[i].getArgument();
if (name.equals("char")) { //$NON-NLS-1$
methodArguments[i] = new Character(arg.charAt(0));
} else if (name.equals("boolean")) { //$NON-NLS-1$
methodArguments[i] = Boolean.valueOf(arg);
} else if (name.equals("int")) { //$NON-NLS-1$
methodArguments[i] = Integer.valueOf(arg);
} else if (name.equals("double")) { //$NON-NLS-1$
methodArguments[i] = Double.valueOf(arg);
} else if (name.equals("float")) { //$NON-NLS-1$
methodArguments[i] = Float.valueOf(arg);
} else if (name.equals("long")) { //$NON-NLS-1$
methodArguments[i] = Long.valueOf(arg);
} else if (name.equals("short")) { //$NON-NLS-1$
methodArguments[i] = Short.valueOf(arg);
} else if (name.equals("byte")) { //$NON-NLS-1$
methodArguments[i] = Byte.valueOf(arg);
} else {
methodArguments[i] = arg;
}
}
timeout = Integer.parseInt(timeoutText.getText());
invocationType = invocationCombo.getSelectionIndex();
super.okPressed();
}
/**
* Returns the method that has been selected by the user.
*
* @return the selected method
*/
public Method getMethod() {
return method;
}
/**
* Returns the arguments that has been specified by the user to pass to the
* method.
*
* @return the list of arguments to pass into the method
*/
public Object[] getMethodArguments() {
return methodArguments;
}
/**
* Retrieves the timeout value that has been specified by the user. This
* value is in milliseconds.
*
* @return the timeout valued specified by the user in milliseconds
*/
public int getTimeout() {
return timeout;
}
/**
* Returns the type of invocation that should be used to call the selected
* method to communicate with a remote service.
*
* @return the invocation type selected by the user
* @see #ASYNC_LISTENER
* @see #ASYNC_FUTURE_RESULT
* @see #ASYNC_FIRE_AND_GO
* @see #OSGI_SERVICE_PROXY
* @see #REMOTE_SERVICE_PROXY
* @see #SYNCHRONOUS
*/
public int getInvocationType() {
return invocationType;
}
}