org.eclipse.ecf.remoteservices.ui.MethodInvocationDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ecf.remoteservices.ui.MethodInvocationDialog.java

Source

/*******************************************************************************
 * 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;
    }
}