com.siteview.mde.internal.ui.shared.target.TargetLocationsGroup.java Source code

Java tutorial

Introduction

Here is the source code for com.siteview.mde.internal.ui.shared.target.TargetLocationsGroup.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2011 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.siteview.mde.internal.ui.shared.target;

import java.util.*;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import com.siteview.mde.internal.core.target.*;
import com.siteview.mde.internal.core.target.provisional.*;
import com.siteview.mde.internal.ui.SWTFactory;
import com.siteview.mde.internal.ui.editor.FormLayoutFactory;
import com.siteview.mde.internal.ui.editor.targetdefinition.TargetEditor;
import com.siteview.mde.internal.ui.wizards.target.TargetDefinitionContentPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.widgets.FormToolkit;

/**
 * UI part that can be added to a dialog or to a form editor.  Contains a table displaying
 * the bundle containers of a target definition.  Also has buttons to add, edit and remove
 * bundle containers of varying types.
 * 
 * @see TargetEditor
 * @see TargetDefinitionContentPage
 * @see ITargetDefinition
 * @see IBundleContainer
 */
public class TargetLocationsGroup {

    private TreeViewer fTreeViewer;
    private Button fAddButton;
    private Button fEditButton;
    private Button fRemoveButton;
    private Button fUpdateButton;
    private Button fShowContentButton;

    private ITargetDefinition fTarget;
    private ListenerList fChangeListeners = new ListenerList();

    /**
     * Creates this part using the form toolkit and adds it to the given composite.
     * 
     * @param parent parent composite
     * @param toolkit toolkit to create the widgets with
     * @return generated instance of the table part
     */
    public static TargetLocationsGroup createInForm(Composite parent, FormToolkit toolkit) {
        TargetLocationsGroup contentTable = new TargetLocationsGroup();
        contentTable.createFormContents(parent, toolkit);
        return contentTable;
    }

    /**
     * Creates this part using standard dialog widgets and adds it to the given composite.
     * 
     * @param parent parent composite
     * @return generated instance of the table part
     */
    public static TargetLocationsGroup createInDialog(Composite parent) {
        TargetLocationsGroup contentTable = new TargetLocationsGroup();
        contentTable.createDialogContents(parent);
        return contentTable;
    }

    /**
     * Private constructor, use one of {@link #createTableInDialog(Composite, ITargetChangedListener)}
     * or {@link #createTableInForm(Composite, FormToolkit, ITargetChangedListener)}.
     * 
     * @param reporter reporter implementation that will handle resolving and changes to the containers
     */
    private TargetLocationsGroup() {

    }

    /**
     * Adds a listener to the set of listeners that will be notified when the bundle containers
     * are modified.  This method has no effect if the listener has already been added. 
     * 
     * @param listener target changed listener to add
     */
    public void addTargetChangedListener(ITargetChangedListener listener) {
        fChangeListeners.add(listener);
    }

    /**
     * Creates the part contents from a toolkit
     * @param parent parent composite
     * @param toolkit form toolkit to create widgets
     */
    private void createFormContents(Composite parent, FormToolkit toolkit) {
        Composite comp = toolkit.createComposite(parent);
        comp.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2));
        comp.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL));

        Tree atree = toolkit.createTree(comp, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
        atree.setLayout(new GridLayout());
        GridData gd = new GridData(GridData.FILL_BOTH);
        atree.setLayoutData(gd);
        atree.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == SWT.DEL && fRemoveButton.getEnabled()) {
                    handleRemove();
                }

            }
        });

        Composite buttonComp = toolkit.createComposite(comp);
        GridLayout layout = new GridLayout();
        layout.marginWidth = layout.marginHeight = 0;
        buttonComp.setLayout(layout);
        buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL));

        fAddButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_0, SWT.PUSH);
        fEditButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_1, SWT.PUSH);
        fRemoveButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_2, SWT.PUSH);
        fUpdateButton = toolkit.createButton(buttonComp, Messages.BundleContainerTable_3, SWT.PUSH);

        fShowContentButton = toolkit.createButton(comp, Messages.TargetLocationsGroup_1, SWT.CHECK);

        initializeTreeViewer(atree);
        initializeButtons();

        toolkit.paintBordersFor(comp);
    }

    /**
     * Creates the part contents using SWTFactory
     * @param parent parent composite
     */
    private void createDialogContents(Composite parent) {
        Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH, 0, 0);

        Tree atree = new Tree(comp, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.MULTI);
        atree.setFont(comp.getFont());
        atree.setLayout(new GridLayout());
        GridData gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = 200;
        atree.setLayoutData(gd);
        atree.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == SWT.DEL && fRemoveButton.getEnabled()) {
                    handleRemove();
                }
            }
        });

        Composite buttonComp = SWTFactory.createComposite(comp, 2, 1, GridData.FILL_BOTH);
        GridLayout layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        buttonComp.setLayout(layout);
        buttonComp.setLayoutData(new GridData(GridData.FILL_VERTICAL));

        fAddButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_0, null);
        fEditButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_1, null);
        fRemoveButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_2, null);
        fUpdateButton = SWTFactory.createPushButton(buttonComp, Messages.BundleContainerTable_3, null);

        fShowContentButton = SWTFactory.createCheckButton(comp, Messages.TargetLocationsGroup_1, null, false, 2);

        initializeTreeViewer(atree);
        initializeButtons();
    }

    /**
     * Sets up the tree viewer using the given tree
     * @param tree
     */
    private void initializeTreeViewer(Tree tree) {
        fTreeViewer = new TreeViewer(tree);
        fTreeViewer.setContentProvider(new BundleContainerContentProvider());
        fTreeViewer.setLabelProvider(new StyledBundleLabelProvider(true, false));
        fTreeViewer.setComparator(new ViewerComparator() {
            public int compare(Viewer viewer, Object e1, Object e2) {
                // Status at the end of the list
                if (e1 instanceof IStatus && !(e2 instanceof IStatus)) {
                    return 1;
                }
                if (e2 instanceof IStatus && !(e1 instanceof IStatus)) {
                    return -1;
                }
                return super.compare(viewer, e1, e2);
            }
        });
        fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateButtons();
            }
        });
        fTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                if (!event.getSelection().isEmpty()) {
                    handleEdit();
                }
            }
        });
        fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
    }

    /**
     * Sets up the buttons, the button fields must already be created before calling this method
     */
    private void initializeButtons() {
        fAddButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleAdd();
            }
        });
        fAddButton.setLayoutData(new GridData());
        SWTFactory.setButtonDimensionHint(fAddButton);

        fEditButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleEdit();
            }
        });
        fEditButton.setLayoutData(new GridData());
        fEditButton.setEnabled(false);
        SWTFactory.setButtonDimensionHint(fEditButton);

        fRemoveButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleRemove();
            }
        });
        fRemoveButton.setLayoutData(new GridData());
        fRemoveButton.setEnabled(false);
        SWTFactory.setButtonDimensionHint(fRemoveButton);

        fUpdateButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleUpdate();
            }
        });
        fUpdateButton.setLayoutData(new GridData());
        fUpdateButton.setEnabled(false);
        SWTFactory.setButtonDimensionHint(fUpdateButton);

        fShowContentButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                fTreeViewer.refresh();
                fTreeViewer.expandAll();
            }
        });
        fShowContentButton.setLayoutData(new GridData());
        SWTFactory.setButtonDimensionHint(fShowContentButton);
    }

    /**
     * Sets the target definition model to use as input for the tree, can be called with different
     * models to change the tree's input.
     * @param target target model
     */
    public void setInput(ITargetDefinition target) {
        fTarget = target;
        fTreeViewer.setInput(fTarget);
        updateButtons();
    }

    private void handleAdd() {
        AddBundleContainerWizard wizard = new AddBundleContainerWizard(fTarget);
        Shell parent = fTreeViewer.getTree().getShell();
        WizardDialog dialog = new WizardDialog(parent, wizard);
        if (dialog.open() != Window.CANCEL) {
            contentsChanged(false);
            fTreeViewer.refresh();
            updateButtons();
        }
    }

    private void handleEdit() {
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        if (!selection.isEmpty()) {
            Object selected = selection.getFirstElement();
            IBundleContainer oldContainer = null;
            if (selected instanceof IBundleContainer) {
                oldContainer = (IBundleContainer) selected;
            } else if (selected instanceof IUWrapper) {
                oldContainer = ((IUWrapper) selected).getParent();
            } else if (selected instanceof IResolvedBundle) {
                TreeItem[] treeSelection = fTreeViewer.getTree().getSelection();
                if (treeSelection.length > 0) {
                    Object parent = treeSelection[0].getParentItem().getData();
                    if (parent instanceof IBundleContainer) {
                        oldContainer = (IBundleContainer) parent;
                    }
                }
            }
            if (oldContainer != null) {
                Shell parent = fTreeViewer.getTree().getShell();
                EditBundleContainerWizard wizard = new EditBundleContainerWizard(fTarget, oldContainer);
                WizardDialog dialog = new WizardDialog(parent, wizard);
                if (dialog.open() == Window.OK) {
                    // Replace the old container with the new one
                    IBundleContainer newContainer = wizard.getBundleContainer();
                    if (newContainer != null) {
                        IBundleContainer[] containers = fTarget.getBundleContainers();
                        java.util.List newContainers = new ArrayList(containers.length);
                        for (int i = 0; i < containers.length; i++) {
                            if (!containers[i].equals(oldContainer)) {
                                newContainers.add(containers[i]);
                            }
                        }
                        newContainers.add(newContainer);
                        fTarget.setBundleContainers((IBundleContainer[]) newContainers
                                .toArray(new IBundleContainer[newContainers.size()]));

                        // Update the table
                        contentsChanged(false);
                        fTreeViewer.refresh();
                        updateButtons();
                        fTreeViewer.setSelection(new StructuredSelection(newContainer), true);
                    }
                }
            }
        }
    }

    private void handleRemove() {
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        IBundleContainer[] containers = fTarget.getBundleContainers();
        if (!selection.isEmpty() && containers != null && containers.length > 0) {
            List toRemove = new ArrayList();
            boolean removedSite = false;
            boolean removedContainer = false;
            for (Iterator iterator = selection.iterator(); iterator.hasNext();) {
                Object currentSelection = iterator.next();
                if (currentSelection instanceof IBundleContainer) {
                    if (currentSelection instanceof IUBundleContainer) {
                        removedSite = true;
                    }
                    removedContainer = true;
                    toRemove.add(currentSelection);
                }
                if (currentSelection instanceof IUWrapper) {
                    toRemove.add(currentSelection);
                }
            }

            if (removedContainer) {
                Set newContainers = new HashSet();
                newContainers.addAll(Arrays.asList(fTarget.getBundleContainers()));
                newContainers.removeAll(toRemove);
                if (newContainers.size() > 0) {
                    fTarget.setBundleContainers(
                            (IBundleContainer[]) newContainers.toArray(new IBundleContainer[newContainers.size()]));
                } else {
                    fTarget.setBundleContainers(null);
                }

                // If we remove a site container, the content change update must force a re-resolve bug 275458 / bug 275401
                contentsChanged(removedSite);
                fTreeViewer.refresh(false);
                updateButtons();
            } else {
                for (Iterator iterator = toRemove.iterator(); iterator.hasNext();) {
                    Object current = iterator.next();
                    if (current instanceof IUWrapper) {
                        ((IUWrapper) current).getParent().removeInstallableUnit(((IUWrapper) current).getIU());
                    }
                }
                contentsChanged(removedSite);
                fTreeViewer.refresh(true);
                updateButtons();
            }
        }
    }

    private void handleUpdate() {
        // go over the selection and make a map from container to set of ius to update.
        // if the set is empty then the whole container is to be updated.
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        Map toUpdate = new HashMap();
        for (Iterator iterator = selection.iterator(); iterator.hasNext();) {
            Object currentSelection = iterator.next();
            if (currentSelection instanceof IBundleContainer)
                toUpdate.put(currentSelection, new HashSet(0));
            else if (currentSelection instanceof IUWrapper) {
                IUWrapper wrapper = (IUWrapper) currentSelection;
                Set iuSet = (Set) toUpdate.get(wrapper.getParent());
                if (iuSet == null) {
                    iuSet = new HashSet();
                    iuSet.add(wrapper.getIU().getId());
                    toUpdate.put(wrapper.getParent(), iuSet);
                } else if (!iuSet.isEmpty())
                    iuSet.add(wrapper.getIU().getId());
            }
        }
        if (toUpdate.isEmpty())
            return;

        JobChangeAdapter listener = new JobChangeAdapter() {
            public void done(final IJobChangeEvent event) {
                Display.getDefault().asyncExec(new Runnable() {
                    public void run() {
                        // XXX what if everything is disposed by the time we get back?
                        UpdateTargetJob job = (UpdateTargetJob) event.getJob();
                        contentsChanged(job.isUpdated());
                        fTreeViewer.refresh(true);
                        try {
                            ITargetHandle currentTarget = TargetPlatformService.getDefault()
                                    .getWorkspaceTargetHandle();
                            if (job.isUpdated() && fTarget.getHandle().equals(currentTarget))
                                LoadTargetDefinitionJob.load(fTarget);
                        } catch (CoreException e) {
                            // do nothing if we could not see the current target.
                        }
                        updateButtons();
                    }
                });
            }
        };
        UpdateTargetJob.update(toUpdate, listener);
    }

    private void updateButtons() {
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        fEditButton.setEnabled(!selection.isEmpty() && (selection.getFirstElement() instanceof IBundleContainer
                || selection.getFirstElement() instanceof IUWrapper));
        // If any container is selected, allow the remove (the remove ignores non-container entries)
        boolean removeAllowed = false;
        boolean updateAllowed = false;
        Iterator iter = selection.iterator();
        while (iter.hasNext()) {
            if (removeAllowed && updateAllowed) {
                break;
            }
            Object current = iter.next();
            if (current instanceof IUBundleContainer) {
                updateAllowed = true;
            }
            if (current instanceof IBundleContainer) {
                removeAllowed = true;
            }
            if (current instanceof IUWrapper) {
                removeAllowed = true;
                updateAllowed = true;
            }
        }
        fRemoveButton.setEnabled(removeAllowed);
        fUpdateButton.setEnabled(updateAllowed);
    }

    /**
     * Informs the reporter for this table that something has changed
     * and is dirty.
     */
    private void contentsChanged(boolean force) {
        Object[] listeners = fChangeListeners.getListeners();
        for (int i = 0; i < listeners.length; i++) {
            ((ITargetChangedListener) listeners[i]).contentsChanged(fTarget, this, true, force);
        }
    }

    /**
     * Content provider for the tree, primary input is a ITargetDefinition, children are IBundleContainers
     */
    class BundleContainerContentProvider implements ITreeContentProvider {

        public Object[] getChildren(Object parentElement) {
            if (parentElement instanceof ITargetDefinition) {
                IBundleContainer[] containers = ((ITargetDefinition) parentElement).getBundleContainers();
                return containers != null ? containers : new Object[0];
            } else if (parentElement instanceof IBundleContainer) {
                IBundleContainer container = (IBundleContainer) parentElement;
                if (container.isResolved()) {
                    IStatus status = container.getStatus();
                    if (!status.isOK() && !status.isMultiStatus()) {
                        return new Object[] { status };
                    }
                    if (fShowContentButton.getSelection()) {
                        return container.getBundles();
                    } else if (!status.isOK()) {
                        // Show multi-status children so user can easily see problems
                        if (status.isMultiStatus()) {
                            return status.getChildren();
                        }
                    } else if (parentElement instanceof IUBundleContainer) {
                        // Show the IUs as children
                        try {
                            // if this is a bundle container then we must be sure that all bundle containers are
                            // happy since they all share the same profile.
                            if (!P2TargetUtils.isResolved(fTarget)) {
                                return new Object[0];
                            }
                            IInstallableUnit[] units = ((IUBundleContainer) parentElement).getInstallableUnits();
                            // Wrap the units so that they remember their parent container
                            List wrappedUnits = new ArrayList(units.length);
                            for (int i = 0; i < units.length; i++) {
                                wrappedUnits.add(new IUWrapper(units[i], (IUBundleContainer) parentElement));
                            }
                            return wrappedUnits.toArray();
                        } catch (CoreException e) {
                            return new Object[] { e.getStatus() };
                        }
                    }
                }
            } else if (parentElement instanceof MultiStatus) {
                return ((MultiStatus) parentElement).getChildren();
            }
            return new Object[0];
        }

        public Object getParent(Object element) {
            if (element instanceof IUWrapper) {
                return ((IUWrapper) element).getParent();
            }
            return null;
        }

        public boolean hasChildren(Object element) {
            // Since we are already resolved we can't be more efficient
            return getChildren(element).length > 0;
        }

        public Object[] getElements(Object inputElement) {
            if (inputElement instanceof ITargetDefinition) {
                boolean hasContainerStatus = false;
                Collection result = new ArrayList();
                IBundleContainer[] containers = ((ITargetDefinition) inputElement).getBundleContainers();
                if (containers != null) {
                    for (int i = 0; i < containers.length; i++) {
                        result.add(containers[i]);
                        if (containers[i].getStatus() != null && !containers[i].getStatus().isOK()) {
                            hasContainerStatus = true;
                        }
                    }
                }
                // If a container has a problem, it is displayed as a child, if there is a status outside of the container status (missing bundle, etc.) put it as a separate item
                if (!hasContainerStatus) {
                    IStatus status = ((ITargetDefinition) inputElement).getBundleStatus();
                    if (status != null && !status.isOK()) {
                        result.add(status);
                    }
                }
                return result.toArray();
            } else if (inputElement instanceof String) {
                return new Object[] { inputElement };
            }
            return new Object[0];
        }

        public void dispose() {
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }

    }

    /**
     * Wraps an installable unit so that it knows what bundle container parent it belongs to
     * in the tree.
     */
    class IUWrapper {
        private IInstallableUnit fIU;
        private IUBundleContainer fParent;

        public IUWrapper(IInstallableUnit unit, IUBundleContainer parent) {
            fIU = unit;
            fParent = parent;
        }

        public IInstallableUnit getIU() {
            return fIU;
        }

        public IUBundleContainer getParent() {
            return fParent;
        }
    }

}