com.ebmwebsourcing.petals.services.wizards.AbstractPetalsServiceCreationWizardPage.java Source code

Java tutorial

Introduction

Here is the source code for com.ebmwebsourcing.petals.services.wizards.AbstractPetalsServiceCreationWizardPage.java

Source

/******************************************************************************
 * Copyright (c) 2010-2013, Linagora
 *
 * 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:
 *       Linagora - initial API and implementation
 *******************************************************************************/

package com.ebmwebsourcing.petals.services.wizards;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ColumnWeightData;
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.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.wizard.WizardPage;
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.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.wst.xml.ui.internal.properties.StringComboBoxCellEditor;

import com.ebmwebsourcing.petals.services.PetalsServicesPlugin;
import com.ebmwebsourcing.petals.services.wizards.beans.SaImportBean;
import com.ebmwebsourcing.petals.services.wizards.beans.ServiceImportBean;
import com.ebmwebsourcing.petals.services.wizards.beans.SuImportBean;

/**
 * A page that shows a tree and widgets to create SU and SA projects.
 * @author Vincent Zurczak - EBM WebSourcing
 */
public abstract class AbstractPetalsServiceCreationWizardPage extends WizardPage {

    private static final String COMPONENT_NAME = "Component";
    private static final String PROJECT_NAME = "Project Name";
    private static final String COMPONENT_VERSION = "Version";
    private static final String CREATE = "Create";
    private final static String OVERWRITE = "Overwrite";

    /**
     * The default array of versions, to use to not make the combo editor crash.
     */
    private final static String[] DEFAULT_VERSIONS = new String[] { "" };

    private Image suImg, saImg;
    private Image checked, unchecked;

    private String projectLocation;
    private boolean complete = false;
    private boolean isAtDefaultLocation = true;

    private TreeViewer viewer;
    private final List<SaImportBean> importsBeans = new ArrayList<SaImportBean>();

    /**
     * Constructor.
     * @param title the page title
     * @param description the page description
     */
    public AbstractPetalsServiceCreationWizardPage(String title, String description) {

        super(title);
        setTitle(title); //NON-NLS-1
        setDescription(description); //NON-NLS-1

        try {
            ImageDescriptor desc = PetalsServicesPlugin.getImageDescriptor("icons/obj16/service_unit.png");
            if (desc != null)
                this.suImg = desc.createImage();

            desc = PetalsServicesPlugin.getImageDescriptor("icons/obj16/service_assembly.png");
            if (desc != null)
                this.saImg = desc.createImage();

            desc = PetalsServicesPlugin.getImageDescriptor("icons/obj16/checked.gif");
            if (desc != null)
                this.checked = desc.createImage();

            desc = PetalsServicesPlugin.getImageDescriptor("icons/obj16/unchecked.gif");
            if (desc != null)
                this.unchecked = desc.createImage();

        } catch (Exception e) {
            PetalsServicesPlugin.log(e, IStatus.WARNING);
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage
     * #createControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    @SuppressWarnings("restriction")
    public void createControl(Composite parent) {

        Composite container = new Composite(parent, SWT.NONE);
        container.setLayout(new GridLayout());
        container.setLayoutData(new GridData(GridData.FILL_BOTH));

        // Before the workspace location
        createWidgetsBeforeProjectLocation(container);

        // Workspace location
        final Button useDefaultLocButton = new Button(container, SWT.CHECK);
        useDefaultLocButton.setText("Create the project(s) in the default location");
        GridData layoutData = new GridData();
        layoutData.verticalIndent = 17;
        useDefaultLocButton.setLayoutData(layoutData);

        Composite locContainer = new Composite(container, SWT.NONE);
        GridLayout layout = new GridLayout(3, false);
        layout.marginHeight = layout.marginWidth = 0;
        locContainer.setLayout(layout);
        locContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        final Label locLabel = new Label(locContainer, SWT.NONE);
        locLabel.setText("Project(s) location:");

        final Text projectLocationText = new Text(locContainer, SWT.SINGLE | SWT.BORDER);
        projectLocationText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        projectLocationText.setText(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString());
        projectLocationText.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                AbstractPetalsServiceCreationWizardPage.this.projectLocation = projectLocationText.getText();
                validate();
            }
        });

        final Button browseButton = new Button(locContainer, SWT.PUSH);
        browseButton.setText("Browse...");
        browseButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                String location = new DirectoryDialog(getShell()).open();
                if (location != null)
                    projectLocationText.setText(location);
            }
        });

        useDefaultLocButton.setSelection(this.isAtDefaultLocation);
        useDefaultLocButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {

                AbstractPetalsServiceCreationWizardPage.this.isAtDefaultLocation = useDefaultLocButton
                        .getSelection();

                boolean use = !AbstractPetalsServiceCreationWizardPage.this.isAtDefaultLocation;
                locLabel.setEnabled(use);
                projectLocationText.setEnabled(use);
                browseButton.setEnabled(use);
                projectLocationText.setFocus();
            }
        });

        // List of projects to create
        Label l = new Label(container, SWT.NONE);
        l.setText("Specify the properties of the target project(s).");

        layoutData = new GridData();
        layoutData.verticalIndent = 17;
        l.setLayoutData(layoutData);

        Tree tree = new Tree(container, SWT.FULL_SELECTION | SWT.BORDER | SWT.SINGLE);
        layoutData = new GridData(GridData.FILL_BOTH);
        layoutData.heightHint = 90;
        tree.setLayoutData(layoutData);
        tree.setHeaderVisible(true);
        tree.setLinesVisible(true);

        TableLayout tlayout = new TableLayout();
        tlayout.addColumnData(new ColumnWeightData(40, 150, false));
        tlayout.addColumnData(new ColumnWeightData(10, 10, false));
        tlayout.addColumnData(new ColumnWeightData(10, 15, false));
        tlayout.addColumnData(new ColumnWeightData(20, 80, true));
        tlayout.addColumnData(new ColumnWeightData(20, 60, true));
        tree.setLayout(tlayout);

        TreeColumn column = new TreeColumn(tree, SWT.LEFT);
        column.setText(PROJECT_NAME);
        column = new TreeColumn(tree, SWT.CENTER);
        column.setText(CREATE);
        column = new TreeColumn(tree, SWT.CENTER);
        column.setText(OVERWRITE);
        column = new TreeColumn(tree, SWT.LEFT);
        column.setText(COMPONENT_NAME);
        column = new TreeColumn(tree, SWT.CENTER);
        column.setText(COMPONENT_VERSION);

        // Create the viewer
        this.viewer = new TreeViewer(tree);

        // Define its content provider
        this.viewer.setContentProvider(new ITreeContentProvider() {

            @Override
            public Object[] getChildren(Object parentElement) {
                Object[] children = new Object[0];
                if (parentElement instanceof SaImportBean) {
                    children = new Object[((SaImportBean) parentElement).countSuBeans()];
                    children = ((SaImportBean) parentElement).getSuBeans().toArray(children);
                }
                return children;
            }

            @Override
            public Object getParent(Object element) {
                return null;
            }

            @Override
            public boolean hasChildren(Object element) {
                boolean hasChildren = false;
                if (element instanceof SaImportBean) {
                    hasChildren = ((SaImportBean) element).countSuBeans() > 0;
                }
                return hasChildren;
            }

            @Override
            public Object[] getElements(Object inputElement) {
                Object[] result = new Object[((Collection<?>) inputElement).size()];
                return ((Collection<?>) inputElement).toArray(result);
            }

            @Override
            public void dispose() {
                // nothing
            }

            @Override
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
                // nothing
            }
        });

        // Define its label provider
        this.viewer.setLabelProvider(new ITableLabelProvider() {
            @Override
            public Image getColumnImage(Object element, int columnIndex) {
                Image result = null;

                switch (columnIndex) {
                case 0:
                    if (element instanceof SaImportBean)
                        result = AbstractPetalsServiceCreationWizardPage.this.saImg;
                    else if (element instanceof SuImportBean)
                        result = AbstractPetalsServiceCreationWizardPage.this.suImg;
                    break;

                case 1:
                    if (element instanceof ServiceImportBean) {
                        result = ((ServiceImportBean) element).isToCreate()
                                ? AbstractPetalsServiceCreationWizardPage.this.checked
                                : AbstractPetalsServiceCreationWizardPage.this.unchecked;
                    }
                    break;

                case 2:
                    if (element instanceof ServiceImportBean) {
                        result = ((ServiceImportBean) element).isToOverwrite()
                                ? AbstractPetalsServiceCreationWizardPage.this.checked
                                : AbstractPetalsServiceCreationWizardPage.this.unchecked;
                    }
                    break;
                }

                return result;
            }

            @Override
            public String getColumnText(Object element, int columnIndex) {
                String result = "";

                switch (columnIndex) {
                case 0:
                    if (element instanceof ServiceImportBean)
                        result = ((ServiceImportBean) element).getProjectName();
                    break;

                case 1:
                case 2:
                    break;

                case 3:
                    if (element instanceof SuImportBean)
                        result = ((SuImportBean) element).getComponentName();
                    break;

                case 4:
                    if (element instanceof SuImportBean)
                        result = ((SuImportBean) element).getComponentVersion();
                    break;
                }

                return result;
            }

            @Override
            public void addListener(ILabelProviderListener listener) {
                // nothing
            }

            @Override
            public void dispose() {
                // nothing
            }

            @Override
            public boolean isLabelProperty(Object element, String property) {
                return false;
            }

            @Override
            public void removeListener(ILabelProviderListener listener) {
                // nothing
            }
        });

        // Define its sorter
        this.viewer.setSorter(new ViewerSorter() {
            @Override
            public int compare(Viewer viewer, Object e1, Object e2) {

                if (e1 instanceof ServiceImportBean && e2 instanceof ServiceImportBean) {
                    String n1 = ((ServiceImportBean) e1).getProjectName();
                    if (n1 == null)
                        n1 = "";

                    String n2 = ((ServiceImportBean) e2).getProjectName();
                    if (n2 == null)
                        n2 = "";

                    return n1.compareTo(n2);
                }

                return super.compare(viewer, e1, e2);
            }
        });

        // Create the editor for the versions (it must be done before creating the cell modifiers).
        // This is done this way to allow the editor to store and retrieve custom values (i.e. versions
        // that are not registered but manually entered by the user).
        final StringComboBoxCellEditor comboEditor = new StringComboBoxCellEditor(tree, DEFAULT_VERSIONS,
                SWT.DROP_DOWN);

        this.viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {

                if (!event.getSelection().isEmpty()) {
                    Object o = ((IStructuredSelection) event.getSelection()).getFirstElement();
                    if (o instanceof SuImportBean) {

                        // If there is a custom value, add it in the list
                        SuImportBean suBean = (SuImportBean) o;
                        List<String> versions = Arrays.asList(suBean.getSupportedVersions());
                        versions = new ArrayList<String>(versions);
                        if (!versions.contains(suBean.getComponentVersion()))
                            versions.add(suBean.getComponentVersion());

                        String[] items = new String[versions.size()];
                        comboEditor.setItems(versions.toArray(items));
                    } else if (o instanceof SaImportBean)
                        comboEditor.setItems(DEFAULT_VERSIONS);
                }
            }
        });

        // Define its cell modifier
        this.viewer.setCellModifier(new ICellModifier() {
            @Override
            public void modify(Object element, String property, Object value) {

                TreeItem tableItem = (TreeItem) element;
                if (PROJECT_NAME.equals(property)) {
                    ServiceImportBean bean = (ServiceImportBean) tableItem.getData();
                    bean.setProjectName((String) value);
                    AbstractPetalsServiceCreationWizardPage.this.viewer.refresh(bean);
                    validate();

                } else if (CREATE.equals(property)) {
                    ServiceImportBean bean = (ServiceImportBean) tableItem.getData();
                    bean.setToCreate((Boolean) value);
                    AbstractPetalsServiceCreationWizardPage.this.viewer.refresh(bean);
                    validate();

                } else if (OVERWRITE.equals(property)) {
                    ServiceImportBean bean = (ServiceImportBean) tableItem.getData();
                    bean.setOverwrite((Boolean) value);
                    AbstractPetalsServiceCreationWizardPage.this.viewer.refresh(bean);
                    validate();

                } else if (tableItem.getData() instanceof SuImportBean) {
                    if (COMPONENT_NAME.equals(property)) {
                        SuImportBean bean = (SuImportBean) tableItem.getData();
                        bean.setComponentName((String) value);
                        AbstractPetalsServiceCreationWizardPage.this.viewer.refresh(bean);
                        validate();

                    } else if (COMPONENT_VERSION.equals(property)) {
                        SuImportBean bean = (SuImportBean) tableItem.getData();
                        bean.setComponentVersion((String) value);
                        AbstractPetalsServiceCreationWizardPage.this.viewer.refresh(bean);
                        validate();
                    }
                }
            }

            @Override
            public Object getValue(Object element, String property) {

                Object value = null;
                if (PROJECT_NAME.equals(property))
                    value = ((ServiceImportBean) element).getProjectName();

                else if (CREATE.equals(property))
                    value = Boolean.valueOf(((ServiceImportBean) element).isToCreate());

                else if (OVERWRITE.equals(property))
                    value = ((ServiceImportBean) element).isToOverwrite();

                else if (element instanceof SuImportBean) {
                    SuImportBean bean = (SuImportBean) element;
                    if (COMPONENT_NAME.equals(property))
                        value = bean.getComponentName();
                    else if (COMPONENT_VERSION.equals(property))
                        value = bean.getComponentVersion();
                }

                return value;
            }

            @Override
            public boolean canModify(Object element, String property) {

                boolean canModify = true;
                if (element instanceof SaImportBean) {
                    canModify = PROJECT_NAME.equals(property) || CREATE.equals(property)
                            || OVERWRITE.equals(property);
                }

                return canModify;
            }
        });

        // End up with the viewer properties
        this.viewer.setColumnProperties(
                new String[] { PROJECT_NAME, CREATE, OVERWRITE, COMPONENT_NAME, COMPONENT_VERSION });

        this.viewer.setCellEditors(new CellEditor[] { new TextCellEditor(tree), new CheckboxCellEditor(tree),
                new CheckboxCellEditor(tree), new TextCellEditor(tree, SWT.READ_ONLY), comboEditor });

        // Last steps
        if (!this.importsBeans.isEmpty()) {
            this.viewer.setInput(this.importsBeans);
            this.viewer.expandAll();
        }

        useDefaultLocButton.notifyListeners(SWT.Selection, new Event());
        tree.notifyListeners(SWT.Selection, new Event());
        validate();
        setErrorMessage(null);
        setControl(container);

        // Force the shell size
        Point size = getShell().computeSize(700, 600);
        getShell().setSize(size);

        Rectangle rect = Display.getCurrent().getBounds();
        getShell().setLocation((rect.width - size.x) / 2, (rect.height - size.y) / 2);
    }

    /**
     * Validates the page entries.
     * @return true if the validation succeeded, false otherwise
     */
    protected boolean validate() {

        // Project location
        if (!this.isAtDefaultLocation) {

            if (this.projectLocation.trim().length() == 0) {
                setErrorMessage("The project(s) location is not specified.");
                setPageComplete(false);
                return false;
            }

            if (!new File(this.projectLocation).exists()) {
                setErrorMessage("The project(s) location is not a valid directory.");
                setPageComplete(false);
                return false;
            }
        }

        // Validate the projects
        Set<String> names = new HashSet<String>();
        for (SaImportBean saBean : this.importsBeans) {
            if (!validateServiceProject(saBean))
                return false;

            for (SuImportBean suBean : saBean.getSuBeans()) {
                if (!validateServiceProject(suBean))
                    return false;

                if (suBean.isToCreate() && !isNameUnique(suBean.getProjectName(), names))
                    return false;
            }

            if (saBean.isToCreate() && !isNameUnique(saBean.getProjectName(), names))
                return false;
        }

        setErrorMessage(null);
        setPageComplete(true);
        return true;
    }

    /**
     * Tests the uniqueness of the project names.
     * @param name the name to check
     * @param names the stores names
     * @return true if this name is unique, false otherwise
     */
    private boolean isNameUnique(String name, Set<String> names) {

        boolean result = true;
        if (names.contains(name)) {
            setErrorMessage("There is a conflict in the project names. " + name + " is already in the list.");
            result = false;

        } else {
            names.add(name);
        }

        setPageComplete(result);
        return result;
    }

    /**
     * Validates the creation of a Petals service project.
     * @param serviceImportBean a service import bean
     * @return true if a project can be created from this bean, false otherwise
     */
    private boolean validateServiceProject(ServiceImportBean serviceImportBean) {

        boolean valid = true;
        if (serviceImportBean.isToCreate()) {
            IWorkspaceRoot wr = ResourcesPlugin.getWorkspace().getRoot();

            // Existing project
            IProject p = wr.getProject(serviceImportBean.getProjectName());
            if (p.exists() && serviceImportBean.isToCreate() && !serviceImportBean.isToOverwrite()) {
                setErrorMessage("The project " + serviceImportBean.getProjectName() + " already exists.");
                setPageComplete(false);
                valid = false;
            }

            // Existing target location ?
            if (!this.isAtDefaultLocation) {
                File f = new File(this.projectLocation, serviceImportBean.getProjectName());
                if (f.exists()) {
                    setErrorMessage("A file already exists at the target location for "
                            + serviceImportBean.getProjectName() + ".");
                    setPageComplete(false);
                    valid = false;
                }
            }
        }

        return valid;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.wizard.WizardPage
     * #isPageComplete()
     */
    @Override
    public boolean isPageComplete() {
        return this.complete;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.wizard.WizardPage
     * #setPageComplete(boolean)
     */
    @Override
    public void setPageComplete(boolean complete) {
        this.complete = complete;
        super.setPageComplete(complete);
    }

    /**
     * @return the importsBeans
     */
    public List<SaImportBean> getImportsBeans() {
        return this.importsBeans;
    }

    /**
     * Adds import beans in the list managed by this class.
     * <p>
     * After insertion, the viewer is refreshed and expanded.
     * </p>
     *
     * @param importBeans the import beans to set (may be null)
     * @param clearBeforeInsertion true to empty the current list before insertion
     */
    public void updateImportBeans(List<SaImportBean> importBeans, boolean clearBeforeInsertion) {

        if (clearBeforeInsertion)
            this.importsBeans.clear();

        if (importBeans != null)
            this.importsBeans.addAll(importBeans);

        if (this.viewer != null) {
            this.viewer.setInput(importBeans);
            this.viewer.refresh();
            this.viewer.expandAll();
        }
    }

    /**
     * @return the isAtDefaultLocation
     */
    public boolean isAtDefaultLocation() {
        return this.isAtDefaultLocation;
    }

    /**
     * @return the projectLocation
     */
    public String getProjectLocation() {
        return this.projectLocation;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.dialogs.DialogPage#dispose()
     */
    @Override
    public void dispose() {

        if (this.viewer.getLabelProvider() != null)
            this.viewer.getLabelProvider().dispose();

        if (this.suImg != null)
            this.suImg.dispose();

        if (this.saImg != null)
            this.saImg.dispose();

        if (this.checked != null)
            this.checked.dispose();

        if (this.unchecked != null)
            this.unchecked.dispose();

        releaseResources();
        super.dispose();
    }

    /**
     * Releases additional resources.
     */
    protected abstract void releaseResources();

    /**
     * Creates the widgets to show before the project location UI part.
     * @param container
     */
    protected abstract void createWidgetsBeforeProjectLocation(Composite container);

}