org.cloudfoundry.ide.eclipse.internal.server.ui.wizards.AbstractCloudFoundryServiceWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudfoundry.ide.eclipse.internal.server.ui.wizards.AbstractCloudFoundryServiceWizardPage.java

Source

/*******************************************************************************
 * Copyright (c) 2012 VMware, Inc.
 * 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:
 *     VMware, Inc. - initial API and implementation
 *******************************************************************************/
package org.cloudfoundry.ide.eclipse.internal.server.ui.wizards;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.cloudfoundry.client.lib.domain.CloudService;
import org.cloudfoundry.client.lib.domain.ServiceConfiguration;
import org.cloudfoundry.ide.eclipse.internal.server.core.CloudFoundryServer;
import org.cloudfoundry.ide.eclipse.internal.server.ui.CloudFoundryImages;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.Observables;
import org.eclipse.core.databinding.observable.map.WritableMap;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.MultiValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.wizard.WizardPageSupport;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.LayoutConstants;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.statushandlers.StatusManager;

public abstract class AbstractCloudFoundryServiceWizardPage extends WizardPage {

    protected DataBindingContext bindingContext;

    private final CloudFoundryServer cloudServer;

    private List<ServiceConfiguration> configurations;

    protected WritableMap map;

    private Text nameText;

    /**
     * The data model.
     */
    protected CloudService service;

    private Composite planDetailsComposite;

    protected Group planGroup;

    private PageBook pageBook;

    private WritableValue planObservable = new WritableValue();

    private Combo typeCombo;

    private Pattern VALID_CHARS = Pattern.compile("[A-Za-z\\$_0-9\\-]+");

    protected AbstractCloudFoundryServiceWizardPage(CloudFoundryServer cloudServer) {
        super("service");
        this.cloudServer = cloudServer;
        setTitle("Service Configuration");
        setDescription("Finish to add the service.");
        ImageDescriptor banner = CloudFoundryImages
                .getWizardBanner(cloudServer.getServer().getServerType().getId());
        if (banner != null) {
            setImageDescriptor(banner);
        }
        this.service = createService();
    }

    public void createControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayoutFactory.fillDefaults().numColumns(2).spacing(10, LayoutConstants.getSpacing().y)
                .applyTo(composite);

        Label label = new Label(composite, SWT.NONE);
        label.setText("Name:");

        nameText = new Text(composite, SWT.BORDER);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(nameText);
        nameText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                service.setName(nameText.getText());
            }
        });

        bindingContext = new DataBindingContext();
        map = new WritableMap();

        WizardPageSupport.create(this, bindingContext);

        bindingContext.bindValue(SWTObservables.observeText(nameText, SWT.Modify),
                Observables.observeMapEntry(map, "name"),
                new UpdateValueStrategy().setAfterConvertValidator(new StringValidator()), null);

        label = new Label(composite, SWT.NONE);
        label.setText("Type:");

        typeCombo = new Combo(composite, SWT.READ_ONLY | SWT.BORDER);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(typeCombo);
        typeCombo.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                int index = typeCombo.getSelectionIndex();
                if (index != -1) {
                    ServiceConfiguration configuration = configurations.get(index);
                    setCloudService(service, configuration);
                }
                refreshPlan();
            }
        });

        bindingContext.bindValue(SWTObservables.observeSelection(typeCombo),
                Observables.observeMapEntry(map, "type"),
                new UpdateValueStrategy().setAfterConvertValidator(new ComboValidator("Select a type")), null);

        pageBook = new PageBook(composite, SWT.NONE);
        GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(pageBook);

        planGroup = new Group(pageBook, SWT.BORDER);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(planGroup);
        planGroup.setLayout(new GridLayout());
        planGroup.setVisible(false);
        planGroup.setText(getPlanLabel());

        MultiValidator validator = new MultiValidator() {
            protected IStatus validate() {
                // access plan value to bind validator
                if (planObservable.getValue() == null) {
                    return ValidationStatus.cancel(getValidationErrorMessage());
                }
                return ValidationStatus.ok();
            }
        };
        bindingContext.addValidationStatusProvider(validator);

        Dialog.applyDialogFont(composite);
        setControl(composite);
    }

    protected CloudService createService() {
        return new CloudService();
    }

    public CloudService getService() {
        return service;
    }

    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible && configurations == null) {
            // delay until dialog is actually visible
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    if (!getControl().isDisposed()) {
                        refresh();
                    }
                }
            });
        }
    }

    protected boolean supportsSpaces() {
        return cloudServer != null && cloudServer.supportsCloudSpaces();
    }

    protected void refresh() {
        if (updateConfiguration()) {
            typeCombo.removeAll();
            for (ServiceConfiguration configuration : configurations) {
                typeCombo.add(configuration.getDescription());
            }
            refreshPlan();
        }
    }

    protected void refreshPlan() {
        int index = typeCombo.getSelectionIndex();
        if (index == -1) {
            pageBook.setVisible(false);
            planGroup.setVisible(false);

            // re-validate
            planObservable.setValue(null);
        } else {
            pageBook.setVisible(true);

            for (Control control : planGroup.getChildren()) {
                control.dispose();
            }
            ServiceConfiguration configuration = configurations.get(index);
            List<ServicePlan> servicePlans = getPlans(configuration);

            if (servicePlans.size() > 1) {
                pageBook.showPage(planGroup);
                planGroup.setVisible(true);

                Button defaultPlanControl = null;

                for (ServicePlan plan : servicePlans) {

                    String planLabelText = plan.getDisplayValue();

                    Button planButton = new Button(planGroup, SWT.RADIO);

                    if (defaultPlanControl == null) {
                        defaultPlanControl = planButton;
                    }

                    planButton.setText(planLabelText);
                    planButton.setData(plan);
                    planButton.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent event) {
                            Button button = (Button) event.widget;
                            if (button.getSelection()) {
                                ServicePlan plan = (ServicePlan) button.getData();
                                setPlan(plan);
                                refreshPlanDetails(plan, planDetailsComposite);
                            }
                        }
                    });
                }

                planDetailsComposite = new Composite(planGroup, SWT.NONE);
                GridLayoutFactory.fillDefaults().extendedMargins(0, 0, 10, 0).numColumns(2)
                        .applyTo(planDetailsComposite);

                // Set a default plan, if one exists
                if (defaultPlanControl != null) {
                    defaultPlanControl.setSelection(true);
                    ServicePlan plan = (ServicePlan) defaultPlanControl.getData();
                    setPlan(plan);
                    refreshPlanDetails(plan, planDetailsComposite);
                }
            } else if (servicePlans.size() == 1) {
                planGroup.setVisible(false);
                ServicePlan plan = servicePlans.get(0);
                setPlan(plan);
            } else {
                pageBook.setVisible(false);
            }
        }
        ((Composite) getControl()).layout(true, true);

    }

    protected void setPlan(ServicePlan plan) {
        plan.updateInService();
        service.getOptions().clear();
        // re-validate
        planObservable.setValue(plan);
    }

    protected boolean updateConfiguration() {
        try {
            getContainer().run(true, false, new IRunnableWithProgress() {
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    try {
                        configurations = cloudServer.getBehaviour().getServiceConfigurations(monitor);
                        Collections.sort(configurations, new Comparator<ServiceConfiguration>() {
                            public int compare(ServiceConfiguration o1, ServiceConfiguration o2) {
                                return o1.getDescription().compareTo(o2.getDescription());
                            }
                        });
                        sortServicePlans(configurations);

                    } catch (CoreException e) {
                        throw new InvocationTargetException(e);
                    } catch (OperationCanceledException e) {
                        throw new InterruptedException();
                    } finally {
                        monitor.done();
                    }
                }
            });
            return true;
        } catch (InvocationTargetException e) {
            IStatus status = cloudServer
                    .error(NLS.bind("Configuration retrieval failed: {0}", e.getCause().getMessage()), e);
            StatusManager.getManager().handle(status, StatusManager.LOG);
            setMessage(status.getMessage(), IMessageProvider.ERROR);
        } catch (InterruptedException e) {
            // ignore
        }
        return false;
    }

    protected class ComboValidator implements IValidator {

        private final String message;

        public ComboValidator(String message) {
            this.message = message;
        }

        public IStatus validate(Object value) {
            if (value instanceof String && ((String) value).length() > 0) {
                return Status.OK_STATUS;
            }
            return ValidationStatus.cancel(message);
        }

    }

    protected class StringValidator implements IValidator {

        public IStatus validate(Object value) {
            if (value instanceof String) {
                if (((String) value).length() == 0) {
                    return ValidationStatus.cancel("Enter a name");
                }
                Matcher matcher = VALID_CHARS.matcher((String) value);
                if (!matcher.matches()) {
                    return ValidationStatus.error("The entered name contains invalid characters.");
                }
            }
            return Status.OK_STATUS;
        }

    }

    abstract protected void refreshPlanDetails(ServicePlan plan, Composite refreshDetailsComposite);

    abstract protected void sortServicePlans(List<ServiceConfiguration> configurations);

    abstract protected List<ServicePlan> getPlans(ServiceConfiguration configuration);

    abstract protected String getValidationErrorMessage();

    abstract protected String getPlanLabel();

    abstract protected void setCloudService(CloudService service, ServiceConfiguration configuration);

    abstract static class ServicePlan {

        private final CloudService service;

        public ServicePlan(CloudService service) {
            this.service = service;
        }

        public CloudService getService() {
            return service;
        }

        abstract public void updateInService();

        abstract protected String getDisplayValue();

    }

}