Package bndtools.editor.project

Source Code of bndtools.editor.project.RunRequirementsPart

package bndtools.editor.project;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.bndtools.api.ILogger;
import org.bndtools.api.Logger;
import org.bndtools.api.ResolveMode;
import org.bndtools.core.resolve.ResolutionResult.Outcome;
import org.bndtools.core.resolve.ResolveJob;
import org.bndtools.core.resolve.ui.ResolutionWizard;
import org.bndtools.core.ui.resource.RequirementLabelProvider;
import org.bndtools.utils.dnd.AbstractViewerDropAdapter;
import org.bndtools.utils.dnd.SupportedTransfer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;

import aQute.bnd.build.Project;
import aQute.bnd.build.model.BndEditModel;
import aQute.bnd.build.model.clauses.VersionedClause;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.resource.CapReqBuilder;
import aQute.bnd.osgi.resource.Filters;
import aQute.bnd.version.Version;
import aQute.libg.filters.AndFilter;
import aQute.libg.filters.Filter;
import aQute.libg.filters.LiteralFilter;
import aQute.libg.filters.Operator;
import aQute.libg.filters.SimpleFilter;
import aQute.libg.qtokens.QuotedTokenizer;
import bndtools.BndConstants;
import bndtools.Plugin;
import bndtools.central.Central;
import bndtools.model.repo.DependencyPhase;
import bndtools.model.repo.ProjectBundle;
import bndtools.model.repo.RepositoryBundle;
import bndtools.model.repo.RepositoryBundleVersion;
import bndtools.wizards.repo.RepoBundleSelectionWizard;

public class RunRequirementsPart extends SectionPart implements PropertyChangeListener {
    private static final ILogger logger = Logger.getLogger(RunRequirementsPart.class);

    private Table table;
    private TableViewer viewer;
    private Button btnAutoResolve;
    private BndEditModel model;

    private List<Requirement> requires;
    private ResolveMode resolveMode;

    private final Image addBundleIcon = AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "icons/brick_add.png").createImage();
    private final Image resolveIcon = AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "icons/wand.png").createImage();

    private ToolItem addBundleTool;
    private ToolItem removeTool;
    private Button btnResolveNow;

    private boolean committing = false;

    public RunRequirementsPart(Composite parent, FormToolkit toolkit, int style) {
        super(parent, toolkit, style);
        createSection(getSection(), toolkit);
    }

    private void createSection(Section section, FormToolkit tk) {
        section.setText("Run Requirements");
        section.setDescription("The specified requirements will be used to resolve a set of runtime bundles from available repositories.");

        // Create toolbar
        ToolBar toolbar = new ToolBar(section, SWT.FLAT);
        section.setTextClient(toolbar);
        fillToolBar(toolbar);

        // Create main panel
        Composite composite = tk.createComposite(section);
        section.setClient(composite);

        table = tk.createTable(composite, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER);
        viewer = new TableViewer(table);
        viewer.setContentProvider(ArrayContentProvider.getInstance());
        viewer.setLabelProvider(new RequirementLabelProvider());

        btnAutoResolve = tk.createButton(composite, "Auto-resolve on save", SWT.CHECK);

        btnResolveNow = tk.createButton(composite, "Resolve", SWT.PUSH);
        btnResolveNow.setImage(resolveIcon);

        // Listeners
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                removeTool.setEnabled(!viewer.getSelection().isEmpty());
            }
        });
        table.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.character == SWT.DEL) {
                    doRemove();
                } else if (e.character == '+') {
                    doAddBundle();
                }
            }
        });
        RequirementViewerDropAdapter dropper = new RequirementViewerDropAdapter();
        dropper.install(viewer);
        btnAutoResolve.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                ResolveMode old = resolveMode;
                resolveMode = btnAutoResolve.getSelection() ? ResolveMode.auto : ResolveMode.manual;
                updateButtonStates();

                if (old != resolveMode)
                    markDirty();
            }
        });
        btnResolveNow.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                doResolve();
            }
        });

        // Layout
        GridLayout layout;
        GridData gd;

        layout = new GridLayout(2, false);
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 5;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        composite.setLayout(layout);

        gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
        gd.widthHint = 50;
        gd.heightHint = 50;
        table.setLayoutData(gd);

        gd = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
        btnResolveNow.setLayoutData(gd);
    }

    private void fillToolBar(ToolBar toolbar) {
        // Add Bundle
        addBundleTool = new ToolItem(toolbar, SWT.PUSH);
        addBundleTool.setImage(addBundleIcon);
        addBundleTool.setToolTipText("Add Bundle Requirement");
        addBundleTool.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                doAddBundle();
            }
        });

        // Remove
        removeTool = new ToolItem(toolbar, SWT.PUSH);
        removeTool.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE));
        removeTool.setDisabledImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE_DISABLED));
        removeTool.setToolTipText("Remove");
        removeTool.setEnabled(false);
        removeTool.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                doRemove();
            }
        });
    }

    private static Requirement createRequirement(Object elem) {
        String bsn = null;
        Version version = null;

        if (elem instanceof RepositoryBundle) {
            bsn = ((RepositoryBundle) elem).getBsn();
        } else if (elem instanceof RepositoryBundleVersion) {
            RepositoryBundleVersion rbv = (RepositoryBundleVersion) elem;
            bsn = rbv.getBundle().getBsn();
            version = rbv.getVersion();
        } else if (elem instanceof ProjectBundle) {
            bsn = ((ProjectBundle) elem).getBsn();
        }

        if (bsn != null) {
            Filter filter = new SimpleFilter(IdentityNamespace.IDENTITY_NAMESPACE, bsn);
            if (version != null) {
                filter = new AndFilter().addChild(filter).addChild(new SimpleFilter("version", Operator.GreaterThanOrEqual, version.toString()));
            }
            Requirement req = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString()).buildSyntheticRequirement();
            return req;
        }
        return null;
    }

    private void doAddBundle() {
        try {
            Project project = getProject();

            RepoBundleSelectionWizard wizard = new RepoBundleSelectionWizard(project, new ArrayList<VersionedClause>(), DependencyPhase.Run);
            wizard.setSelectionPageTitle("Add Bundle Requirement");
            WizardDialog dialog = new WizardDialog(getSection().getShell(), wizard);

            if (Window.OK == dialog.open()) {
                List<VersionedClause> result = wizard.getSelectedBundles();
                List<Requirement> adding = new ArrayList<Requirement>(result.size());
                for (VersionedClause bundle : result) {
                    Filter filter = new SimpleFilter(IdentityNamespace.IDENTITY_NAMESPACE, bundle.getName());

                    String versionRange = bundle.getVersionRange();
                    if (versionRange != null && !"latest".equals(versionRange)) {
                        filter = new AndFilter().addChild(filter).addChild(new LiteralFilter(Filters.fromVersionRange(versionRange)));
                    }
                    Requirement req = new CapReqBuilder(IdentityNamespace.IDENTITY_NAMESPACE).addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString()).buildSyntheticRequirement();
                    adding.add(req);
                }
                if (!adding.isEmpty()) {
                    requires.addAll(adding);
                    viewer.add(adding.toArray(new Object[adding.size()]));
                    markDirty();
                }
            }
        } catch (Exception e) {
            ErrorDialog.openError(getSection().getShell(), "Error", null, new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, "Error selecting bundles.", e));
        }

    }

    private void doRemove() {
        IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        if (!selection.isEmpty()) {
            Iterator< ? > elements = selection.iterator();
            List<Object> removed = new LinkedList<Object>();
            while (elements.hasNext()) {
                Object element = elements.next();
                if (requires.remove(element))
                    removed.add(element);
            }

            if (!removed.isEmpty()) {
                viewer.remove(removed.toArray(new Object[removed.size()]));
                markDirty();
            }
        }
    }

    private void doResolve() {
        // Make sure all the parts of this editor page have committed their
        // dirty state to the model
        IFormPart[] parts = getManagedForm().getParts();
        for (IFormPart part : parts) {
            if (part.isDirty())
                part.commit(false);
        }

        IFormPage page = (IFormPage) getManagedForm().getContainer();
        IEditorInput input = page.getEditorInput();
        final IFile file = ResourceUtil.getFile(input);

        final Shell parentShell = page.getEditor().getSite().getShell();

        // Create the wizard and pre-validate
        final ResolveJob job = new ResolveJob(model);
        IStatus validation = job.validateBeforeRun();
        if (!validation.isOK()) {
            ErrorDialog errorDialog = new ErrorDialog(parentShell, "Validation Problem", null, validation, IStatus.ERROR | IStatus.WARNING) {
                @Override
                protected void createButtonsForButtonBar(Composite parent) {
                    // create OK, Cancel and Details buttons
                    createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false);
                    createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true);
                    createDetailsButton(parent);
                }
            };
            int response = errorDialog.open();
            if (Window.CANCEL == response || validation.getSeverity() >= IStatus.ERROR)
                return;
        }

        // Add the operation to perform at the end of the resolution job (i.e.,
        // showing the result)
        final Runnable showResult = new Runnable() {
            public void run() {
                ResolutionWizard wizard = new ResolutionWizard(model, file, job.getResolutionResult());
                WizardDialog dialog = new WizardDialog(parentShell, wizard);
                dialog.open();
            }
        };
        job.addJobChangeListener(new JobChangeAdapter() {
            @Override
            public void done(IJobChangeEvent event) {
                Outcome outcome = job.getResolutionResult().getOutcome();
                if (outcome != Outcome.Cancelled)
                    parentShell.getDisplay().asyncExec(showResult);
            }
        });

        job.setUser(true);
        job.schedule();
    }

    @Override
    public void initialize(IManagedForm form) {
        super.initialize(form);

        model = (BndEditModel) form.getInput();

        model.addPropertyChangeListener(BndConstants.RUNREQUIRE, this);
        model.addPropertyChangeListener(BndConstants.RUNREQUIRES, this);
        model.addPropertyChangeListener(BndConstants.RESOLVE_MODE, this);
    }

    @Override
    public void dispose() {
        model.removePropertyChangeListener(BndConstants.RUNREQUIRE, this);
        model.removePropertyChangeListener(BndConstants.RUNREQUIRES, this);
        model.removePropertyChangeListener(BndConstants.RESOLVE_MODE, this);

        super.dispose();

        addBundleIcon.dispose();
        resolveIcon.dispose();
    }

    @Override
    public void commit(boolean onSave) {
        super.commit(onSave);
        try {
            committing = true;
            model.setRunRequires(requires);
            model.genericSet(Constants.RUNREQUIRE, null);
            setResolveMode();
        } finally {
            committing = false;
        }
    }

    @Override
    public void refresh() {
        List<Requirement> tmp = model.getRunRequires();
        if (tmp == null) {
            String legacyReqStr = (String) model.genericGet(Constants.RUNREQUIRE);
            if (legacyReqStr != null) {
                tmp = convertLegacyRequireList(legacyReqStr);
            }
        }

        requires = new ArrayList<Requirement>(tmp != null ? tmp : Collections.<Requirement> emptyList());
        viewer.setInput(requires);

        resolveMode = getResolveMode();
        btnAutoResolve.setSelection(resolveMode == ResolveMode.auto);
        updateButtonStates();

        super.refresh();
    }

    private void setResolveMode() {
        String formatted;
        if (resolveMode == ResolveMode.manual || resolveMode == null)
            formatted = null;
        else
            formatted = resolveMode.toString();
        model.genericSet(BndConstants.RESOLVE_MODE, formatted);
    }

    private ResolveMode getResolveMode() {
        ResolveMode resolveMode = ResolveMode.manual;
        try {
            String str = (String) model.genericGet(BndConstants.RESOLVE_MODE);
            if (str != null)
                resolveMode = Enum.valueOf(ResolveMode.class, str);
        } catch (Exception e) {
            logger.logError("Error parsing '-resolve' header.", e);
        }
        return resolveMode;
    }

    private List<Requirement> convertLegacyRequireList(String input) throws IllegalArgumentException {
        List<Requirement> result = new ArrayList<Requirement>();
        if (Constants.EMPTY_HEADER.equalsIgnoreCase(input.trim()))
            return result;

        QuotedTokenizer qt = new QuotedTokenizer(input, ",");
        String token = qt.nextToken();

        while (token != null) {
            String item = token.trim();
            int index = item.indexOf(":");
            if (index < 0)
                throw new IllegalArgumentException("Invalid format for requirement");

            String name = item.substring(0, index);
            String filter = item.substring(index + 1);
            Requirement req = new CapReqBuilder(name).addDirective(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter).buildSyntheticRequirement();
            result.add(req);

            token = qt.nextToken();
        }

        return result;
    }

    private void updateButtonStates() {
        // btnResolveNow.setEnabled(resolveMode != ResolveMode.auto);
    }

    public void propertyChange(PropertyChangeEvent evt) {
        if (!committing) {
            IFormPage page = (IFormPage) getManagedForm().getContainer();
            if (page.isActive()) {
                refresh();
            } else {
                markStale();
            }
        }
    }

    private class RequirementViewerDropAdapter extends AbstractViewerDropAdapter {

        public RequirementViewerDropAdapter() {
            super(viewer, EnumSet.of(SupportedTransfer.LocalSelection));
        }

        @Override
        protected boolean performSelectionDrop(ISelection data, Object target, int location) {
            List<Requirement> adding = new LinkedList<Requirement>();

            if (data instanceof IStructuredSelection) {
                IStructuredSelection structSel = (IStructuredSelection) data;

                for (Object elem : structSel.toList()) {
                    Requirement requirement = createRequirement(elem);
                    if (requirement != null)
                        adding.add(requirement);
                }
            }

            if (!adding.isEmpty()) {
                requires.addAll(adding);
                viewer.add(adding.toArray(new Object[adding.size()]));
                markDirty();
                return true;
            }
            return false;
        }
    }

    Project getProject() {
        Project project = null;
        try {
            BndEditModel model = (BndEditModel) getManagedForm().getInput();
            File bndFile = model.getBndResource();
            IPath path = Central.toPath(bndFile);
            IFile resource = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
            File projectDir = resource.getProject().getLocation().toFile();
            if (Project.BNDFILE.equals(resource.getName())) {
                project = Central.getProject(projectDir);
            } else {
                project = new Project(Central.getWorkspace(), projectDir, resource.getLocation().toFile());
            }
        } catch (Exception e) {
            logger.logError("Error getting project from editor model", e);
        }
        return project;
    }

}
TOP

Related Classes of bndtools.editor.project.RunRequirementsPart

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.