org.eclipse.oomph.setup.ui.wizards.ConfigurationProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.oomph.setup.ui.wizards.ConfigurationProcessor.java

Source

/*
 * Copyright (c) 2016 Ed Merks (Berlin, Germany) 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:
 *    Ed Merks - initial API and implementation
 */
package org.eclipse.oomph.setup.ui.wizards;

import org.eclipse.oomph.base.util.BaseUtil;
import org.eclipse.oomph.setup.Configuration;
import org.eclipse.oomph.setup.EclipseIniTask;
import org.eclipse.oomph.setup.Index;
import org.eclipse.oomph.setup.Installation;
import org.eclipse.oomph.setup.Product;
import org.eclipse.oomph.setup.ProductCatalog;
import org.eclipse.oomph.setup.ProductVersion;
import org.eclipse.oomph.setup.Project;
import org.eclipse.oomph.setup.ProjectCatalog;
import org.eclipse.oomph.setup.ProjectContainer;
import org.eclipse.oomph.setup.Scope;
import org.eclipse.oomph.setup.SetupFactory;
import org.eclipse.oomph.setup.SetupTask;
import org.eclipse.oomph.setup.SetupTaskContainer;
import org.eclipse.oomph.setup.Stream;
import org.eclipse.oomph.setup.Workspace;
import org.eclipse.oomph.setup.WorkspaceTask;
import org.eclipse.oomph.setup.internal.core.SetupContext;
import org.eclipse.oomph.setup.internal.core.util.CatalogManager;
import org.eclipse.oomph.setup.ui.SetupUIPlugin;
import org.eclipse.oomph.util.StringUtil;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * @author Ed Merks
 */
public class ConfigurationProcessor {
    protected final SetupWizard setupWizard;

    protected final Configuration configuration;

    protected final Workspace workspace;

    protected Installation installation;

    private final ScopeStatus status = new ScopeStatus(null,
            "Problems were encountered processing the configuration");

    public ConfigurationProcessor(SetupWizard setupWizard) {
        this.setupWizard = setupWizard;
        configuration = setupWizard.getConfiguration();
        if (configuration == null) {
            installation = null;
            workspace = null;
        } else {
            installation = configuration.getInstallation();
            workspace = configuration.getWorkspace();
        }

        status.add(new ScopeStatus(installation, "Problems were encountered processing the installation"));
        status.add(new ScopeStatus(null, "Problems were encountered processing the workspace"));
    }

    public IStatus getStatus() {
        status.computeSeverity();

        int okCount = 0;
        IStatus result = null;
        for (IStatus status : status.getChildren()) {
            if (status.isOK()) {
                ++okCount;
            } else {
                result = status;
            }
        }

        if (okCount == 1) {
            return result;
        }

        return status;
    }

    public boolean processInstallation() {
        return installation == null ? handleNullInstallation() : handleInstallation();
    }

    protected MultiStatus getStatus(final Scope scope) {
        if (scope instanceof Installation) {
            return (MultiStatus) status.getChildren()[0];
        }

        MultiStatus containerStatus = (MultiStatus) status.getChildren()[scope instanceof ProductVersion ? 0 : 1];
        for (IStatus status : containerStatus.getChildren()) {
            ScopeStatus scopeStatus = (ScopeStatus) status;
            if (scopeStatus.getScope() == scope) {
                return scopeStatus;
            }
        }

        ScopeStatus scopeStatus = new ScopeStatus(scope);
        containerStatus.add(scopeStatus);
        return scopeStatus;
    }

    public boolean processWorkspace() {
        return workspace == null ? handleNullWorkspace() : handleWorkspace();
    }

    protected boolean handleNullInstallation() {
        return true;
    }

    protected boolean handleInstallation() {
        ProductVersion productVersion = installation.getProductVersion();
        return productVersion == null ? handleNullProductVersion() : handleProductVersion(productVersion);
    }

    protected boolean handleNullProductVersion() {
        addStatus(IStatus.ERROR, installation, "No product version is specified");
        return false;
    }

    protected boolean handleProductVersion(ProductVersion productVersion) {
        if (productVersion.eIsProxy()) {
            return handleProxyProductVersion(productVersion);
        }

        Product product = productVersion.getProduct();
        if (product == null) {
            return handleNullProduct(productVersion);
        }

        ProductCatalog productCatalog = product.getProductCatalog();
        CatalogManager catalogManager = setupWizard.getCatalogManager();
        if (productCatalog == null) {
            boolean added = false;
            CatalogSelector catalogSelector = new CatalogSelector(catalogManager, true);
            for (Scope scope : catalogSelector.getCatalogs()) {
                if (isUserProductCatalog(scope)) {
                    ProductCatalog userProductCatalog = (ProductCatalog) scope;
                    userProductCatalog.getProducts().add(product);
                    BaseUtil.saveEObject(userProductCatalog);
                    catalogManager.selectCatalog(true, userProductCatalog, true);
                    added = true;
                    break;
                }
            }

            if (!added) {
                return handleNoUserProductCatalog(productVersion);
            }
        } else {
            Index index = catalogManager.getIndex();
            Index productCatalogIndex = productCatalog.getIndex();
            if (productCatalogIndex == index) {
                if (!"self".equals(productCatalog.getName())) {
                    catalogManager.selectCatalog(true, productCatalog, true);
                }
            } else if (!addCatalog(true, productCatalog, productVersion)) {
                return handleNoRedirectableProductCatalog(productVersion);
            }
        }

        if ("self.empty.product.version".equals(productVersion.getQualifiedName())) {
            return applyEmptyProductVersion();
        }

        return applyProductVersion(productVersion);
    }

    protected boolean applyEmptyProductVersion() {
        return false;
    }

    protected boolean applyProductVersion(ProductVersion productVersion) {
        return false;
    }

    protected void applyInstallation() {
        SetupContext setupContext = SetupContext.create(setupWizard.getResourceSet(), null);
        Installation setupInstallation = setupContext.getInstallation();

        applyAttributes(setupInstallation, installation);
        applySetupTasks(setupInstallation, installation);

        setupWizard.addAppliedConfigurationResource(installation.eResource());
    }

    protected void applyAttributes(Scope targetScope, Scope sourceScope) {
        String name = sourceScope.getName();
        if (!StringUtil.isEmpty(name)) {
            targetScope.setName(name);
        }

        String label = sourceScope.getLabel();
        if (!StringUtil.isEmpty(label)) {
            targetScope.setLabel(label);
        }

        String description = sourceScope.getDescription();
        if (!StringUtil.isEmpty(description)) {
            targetScope.setDescription(description);
        }

        targetScope.getAnnotations().addAll(sourceScope.getAnnotations());
    }

    protected void applySetupTasks(SetupTaskContainer targetSetupTaskContainer,
            SetupTaskContainer sourceSetTaskContainer) {
        targetSetupTaskContainer.getSetupTasks().addAll(sourceSetTaskContainer.getSetupTasks());
    }

    protected boolean handleNoRedirectableProductCatalog(ProductVersion productVersion) {
        return false;
    }

    protected boolean handleNoUserProductCatalog(ProductVersion productVersion) {
        addStatus(IStatus.ERROR, productVersion,
                "Cannot add the product to the user product catalog because the index doesn't contain one");
        return false;
    }

    protected boolean handleProxyProductVersion(ProductVersion productVersion) {
        addStatus(IStatus.ERROR, productVersion, "The product version cannot be resolved");
        return false;
    }

    protected boolean handleNullProduct(ProductVersion productVersion) {
        addStatus(IStatus.ERROR, productVersion, "The product version is not contained by a product");
        return false;
    }

    protected boolean handleNullWorkspace() {
        return true;
    }

    protected boolean handleWorkspace() {
        if (setupWizard.isSimple()) {
            int answer = new MessageDialog(setupWizard.getShell(), "Configuration Handling", null,
                    "The configuration contains a workspace that can only be handled by the advanced mode of the installer.",
                    MessageDialog.WARNING, installation == null ? //
                            new String[] { "Switch to Advanced Mode", "Cancel" } : //
                            new String[] { "Switch to Avanced Mode", "Apply only Installation", "Cancel" },
                    0).open();
            switch (answer) {
            case 0: {
                if (configuration != null) {
                    setupWizard.addAppliedConfigurationResource(configuration.eResource());
                }

                Collection<? extends Resource> configurationResources = setupWizard
                        .getAppliedConfigurationResources();
                handleSwitchToAdvancedMode();
                setupWizard.setConfigurationResources(configurationResources);
                return false;
            }

            case 1: {
                if (installation != null) {
                    return true;
                }

                return false;
            }

            default: {
                return false;
            }
            }
        }

        List<Stream> projectStreams = new ArrayList<Stream>();
        for (Stream stream : workspace.getStreams()) {
            if (stream.eIsProxy()) {
                addStatus(IStatus.ERROR, stream, "The referenced stream cannot be resolved");
            } else {
                Project project = stream.getProject();
                if (project == null) {
                    addStatus(IStatus.ERROR, stream, "The referenced stream is not contained by a project");
                } else {
                    Project rootProject = project;
                    ProjectCatalog projectCatalog = null;
                    for (ProjectContainer projectContainer = project
                            .getProjectContainer(); projectContainer != null; projectContainer = projectContainer
                                    .getProjectContainer()) {
                        if (projectContainer instanceof Project) {
                            rootProject = (Project) projectContainer;
                        } else if (projectContainer instanceof ProjectCatalog) {
                            projectCatalog = (ProjectCatalog) projectContainer;
                            break;
                        }
                    }

                    if (projectCatalog == null) {
                        ProjectContainer logicalProjectContainer = rootProject.getLogicalProjectContainer();
                        if (logicalProjectContainer == null) {
                            addStatus(IStatus.ERROR, stream,
                                    "The referenced stream's root project is not contained by a project catalog and it doesn't specify a logical project container: "
                                            + EcoreUtil.getURI(rootProject));
                        } else if (logicalProjectContainer.eIsProxy()) {
                            addStatus(IStatus.ERROR, stream,
                                    "The referenced stream's root project is not contained by a project catalog and its logical project container cannot be resolved: "
                                            + EcoreUtil.getURI(logicalProjectContainer));
                        } else if (logicalProjectContainer instanceof Project) {
                            addStatus(IStatus.ERROR, stream,
                                    "The referenced stream's root project is not contained by a project catalog and is not contained by its logical project container: "
                                            + EcoreUtil.getURI(logicalProjectContainer));
                        } else {
                            // Try to add the catalog.
                            ProjectCatalog logicalProjectCatalog = (ProjectCatalog) logicalProjectContainer;
                            if (handleStream(logicalProjectCatalog, stream)) {
                                // If the project is in that catalog, we're all good.
                                if (logicalProjectCatalog.getProjects().contains(rootProject)) {
                                    projectStreams.add(stream);
                                }
                                // Try to add the root project to the user extension project of the catalog.
                                else if (handleUserProject(logicalProjectCatalog, rootProject)) {
                                    projectStreams.add(stream);
                                } else {
                                    addStatus(IStatus.ERROR, stream, "Cannot add the stream's root project: "
                                            + EcoreUtil.getURI(rootProject));
                                    addStatus(IStatus.ERROR, stream,
                                            "The target project catalog does not contain an extensible user project: "
                                                    + EcoreUtil.getURI(logicalProjectCatalog));
                                }
                            } else {
                                // Errors already handled.
                            }
                        }
                    } else {
                        if (handleStream(projectCatalog, stream)) {
                            projectStreams.add(stream);
                        } else {
                            // Errors already handled.
                        }
                    }
                }
            }
        }

        if (projectStreams.isEmpty() ? applyNoStreams() : applyStreams(projectStreams)) {
            return applyWorkspace();
        }

        return false;
    }

    protected boolean applyWorkspace() {
        SetupContext setupContext = SetupContext.create(installation, Collections.<Stream>emptyList(), null);
        Workspace setupWorkspace = setupContext.getWorkspace();

        applyAttributes(setupWorkspace, workspace);
        applySetupTasks(setupWorkspace, workspace);

        if (setupWorkspace.getStreams().isEmpty() && !setupWorkspace.getSetupTasks().isEmpty()) {
            WorkspaceTask workspaceTask = SetupFactory.eINSTANCE.createWorkspaceTask();
            workspaceTask.setID("workspace");
            setupWorkspace.getSetupTasks().add(0, workspaceTask);
        }

        setupWizard.addAppliedConfigurationResource(workspace.eResource());

        return true;
    }

    protected boolean applyStreams(List<Stream> streams) {
        return true;
    }

    protected boolean applyNoStreams() {
        return true;
    }

    protected boolean handleNoRedirectableProjectCatalog(Stream stream) {
        return false;
    }

    protected boolean handleUserProject(ProjectCatalog projectCatalog, Project project) {
        CatalogManager catalogManager = setupWizard.getCatalogManager();
        for (Project catalogProject : projectCatalog.getProjects()) {
            if (isUserProject(catalogProject)) {
                catalogProject.getProjects().add(project);
                BaseUtil.saveEObject(catalogProject);
                catalogManager.selectCatalog(false, projectCatalog, true);
                return true;
            }
        }

        // addStatus(IStatus.ERROR, , message);

        return false;
    }

    protected boolean handleStream(ProjectCatalog projectCatalog, Stream stream) {
        CatalogManager catalogManager = setupWizard.getCatalogManager();
        Index projectIndex = projectCatalog.getIndex();
        Index index = catalogManager.getIndex();
        if (projectIndex != index && !addCatalog(false, projectCatalog, stream)) {
            return handleNoRedirectableProjectCatalog(stream);
        }

        catalogManager.selectCatalog(false, projectCatalog, true);

        return true;
    }

    protected boolean addCatalog(boolean product, Scope catalogScope, Scope originatingScope) {
        CatalogManager catalogManager = setupWizard.getCatalogManager();
        Scope catalog = catalogManager.getCatalog(product, "redirectable");
        String label = product ? "product" : "project";
        if (catalog == null) {
            addStatus(IStatus.ERROR, originatingScope, "Cannot add the catalog " + EcoreUtil.getURI(catalogScope));

            ResourceSet resourceSet = setupWizard.getResourceSet();
            Resource resource = resourceSet.getResource(URI.createURI("index:/redirectable." + label + "s.setup"),
                    false);
            if (resource == null) {
                addStatus(IStatus.ERROR, originatingScope,
                        "There is no redirectable " + label + " catalog is in the index");
            } else {
                addStatus(IStatus.ERROR, originatingScope,
                        "The redirectable " + label + " catalog in the index is already redirected to "
                                + resourceSet.getURIConverter().normalize(resource.getURI()));
            }

            return false;
        }

        Resource catalogResource = catalog.eResource();
        URI sourceURI = catalogResource.getURI();
        URI targetURI = catalogScope.eResource().getURI();
        EcoreUtil.replace(catalog, catalogScope);
        catalogManager.selectCatalog(product, catalogScope, true);
        catalogResource.getResourceSet().getURIConverter().getURIMap().put(targetURI, sourceURI);

        EList<SetupTask> setupTasks = (product ? installation : workspace).getSetupTasks();
        EclipseIniTask redirectionEclipseIniTask = SetupFactory.eINSTANCE.createEclipseIniTask();
        redirectionEclipseIniTask.setVm(true);
        redirectionEclipseIniTask.setOption("-Doomph.redirection." + (product ? "products" : "projects") + "=");
        redirectionEclipseIniTask.setValue(sourceURI + "->" + targetURI);
        setupTasks.add(0, redirectionEclipseIniTask);

        return true;
    }

    protected void addStatus(int severity, Scope scope, String message) {
        MultiStatus containerStatus = getStatus(scope);
        containerStatus.add(new Status(severity, SetupUIPlugin.PLUGIN_ID, message));
    }

    protected void handleSwitchToAdvancedMode() {
    }

    public static boolean isUserProject(Project project) {
        Resource resource = project.eResource();
        return resource != null && SetupContext.isUserScheme(resource.getURI().scheme());
    }

    public static boolean isUserProductCatalog(Scope scope) {
        if (scope instanceof ProductCatalog) {
            Resource resource = scope.eResource();
            return resource != null && SetupContext.isUserScheme(resource.getURI().scheme());
        }

        return false;
    }

    private static class ScopeStatus extends MultiStatus {
        private final Scope scope;

        public ScopeStatus(Scope scope) {
            super(SetupUIPlugin.PLUGIN_ID, 0, "Processing " + EcoreUtil.getURI(scope), null);
            this.scope = scope;
        }

        public ScopeStatus(Scope scope, String message) {
            super(SetupUIPlugin.PLUGIN_ID, 0, message, null);
            this.scope = scope;
        }

        public Scope getScope() {
            return scope;
        }

        public int computeSeverity() {
            for (IStatus status : getChildren()) {
                int newSev = status instanceof ScopeStatus ? ((ScopeStatus) status).computeSeverity()
                        : status.getSeverity();
                if (newSev > getSeverity()) {
                    setSeverity(newSev);
                }
            }

            return getSeverity();
        }
    }
}