Constructing the Eclipse application model. This tutorial provides an introduction to using the EMF API to persist part of the application model.

1. Influence the application model persistence

1.1. Specifying the location of the application model file

The file name and location of the application model can be specified in the plugin.xml file. This is done via the applicationXMI property. The path to the file follows the "bundleSymbolicName"/"filename" pattern, e.g., test/ApplicationDifferent.e4xmi.

To achieve this open the plugin.xml file. Select the Extensions tab and open the org.eclipse.core.runtime.products contribution.

Right-click on the product entry and select menu:New [Property]. Use applicationXMI as parameter name and com.vogella.tasks.ui/ApplicationNew.e4xmi as a value. This value consists of the BundleSymbolicName of the corresponding plug-in and the application model file name.

tutorial product70

2. Custom application model persistence handler

Eclipse uses an instance of the IModelResourceHandler interface to load and save the application model at startup and shutdown. The default implementation is provided by the ResourceHandler class from the org.eclipse.e4.ui.internal.workbench package.

You can specify the modelResourceHandler as parameter on your product extension to use another class to construct the initial application model.

modelresourcehandler

This allows you to construct the initial application model from any source you desire. For example, you could use property files or construct the application model based on information from a database.

Implementing this interface requires knowledge of the Eclipse Modeling Framework (EMF). You can use the ResourceHandler as a template to see how the IModelResourceHandler interface could be implemented.

3. Optional exercise: Using files for perspective persistence

In this exercise, you persist the active perspective in an external file. It requires that your application model uses perspectives.

3.1. Create the plug-in and add dependencies

Create a new simple plug-in named com.vogella.rcp.persistence.handlers.

Add the following dependencies to its MANIFEST.MF file.

  • org.eclipse.e4.core.di

  • org.eclipse.e4.ui.model.workbench

  • org.eclipse.e4.ui.workbench

  • org.eclipse.emf.ecore

  • org.eclipse.emf.ecore.xmi

  • org.eclipse.jface

  • org.eclipse.swt

3.2. Implement a persistence handler

The following handler saves the model elements of the active perspective into an XMI file.

package com.vogella.rcp.persistence.handlers;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;

public class SavePerspectiveHandler {

    @Execute
    public void execute(EModelService modelService, MWindow window, Shell shell) {

        // store model of the active perspective
        MPerspective activePerspective = modelService.getActivePerspective(window);
        if (activePerspective == null) {
            MessageDialog.openInformation(shell, "No perspective found", "Are you using perspectives?");
            // no perspective found, return
            return;
        }

        // create a resource, which is able to store e4 model elements
        @SuppressWarnings("restriction")
        E4XMIResourceFactory e4xmiResourceFactory = new E4XMIResourceFactory();
        Resource resource = e4xmiResourceFactory.createResource(null);

        // You must clone the perspective, otherwise the running application
        // would break, because adding the element to the resource removes it
        // from the running application model
        MUIElement clonedPerspective = modelService.cloneElement(activePerspective, null);

        // add the cloned model element to the resource so that it may be stored
        resource.getContents().add((EObject) clonedPerspective);

        try (FileOutputStream outputStream = new FileOutputStream(getFileNameForPersistence())) {
            resource.save(outputStream, null);
            MessageDialog.openInformation(shell, "Persisted perspective", "Persisted as " + getFileNameForPersistence());
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    static String getFileNameForPersistence() {
        String currentUsersHomeDir = System.getProperty("user.home");
        return currentUsersHomeDir + File.separator + ".eclipse/perspective.xml";
    }
}

3.3. Load stored model elements

You can load the XMI file via the load method of the Resource class.

The following handler applies the stored perspective to the application model. It removes existing perspectives with the same elementId as the loaded perspective, adds the loaded perspective and switches to it.

package com.vogella.rcp.persistence.handlers;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;

public class LoadPerspectiveHandler {

    @Execute
    public void execute(EPartService partService, EModelService modelService, EPlaceholderResolver resolver,
            MWindow window, Shell shell) throws IOException {

        MPerspective activePerspective = modelService.getActivePerspective(window);
        if (activePerspective == null) {
            return;
        }

        // create a resource, which is able to load e4 model elements
        @SuppressWarnings("restriction")
        E4XMIResourceFactory e4xmiResourceFactory = new E4XMIResourceFactory();
        Resource resource = e4xmiResourceFactory.createResource(null);

        try (FileInputStream inputStream = new FileInputStream(SavePerspectiveHandler.getFileNameForPersistence())) {

            // load the stored model element
            resource.load(inputStream, null);

            if (!resource.getContents().isEmpty()) {

                // after the model element is loaded it can be obtained from the
                // contents of the resource
                MPerspective loadedPerspective = (MPerspective) resource.getContents().get(0);

                // get the parent perspective stack, so that the loaded
                // perspective can be added to it.
                MElementContainer<MUIElement> perspectiveParent = activePerspective.getParent();

                // remove the perspectives which should be replaced by the loaded one
                List<MPerspective> alreadyPresentPerspective = modelService.findElements(window,
                        loadedPerspective.getElementId(), MPerspective.class, null);
                for (MPerspective perspective : alreadyPresentPerspective) {
                    modelService.removePerspectiveModel(perspective, window);
                }

                // add the loaded perspective and switch to it
                perspectiveParent.getChildren().add(loadedPerspective);

                // the loaded placeholders do not reference their shared parts yet
                for (MPlaceholder placeholder : modelService.findElements(loadedPerspective, null, MPlaceholder.class, null)) {
                    resolver.resolvePlaceholderRef(placeholder, window);
                }

                partService.switchPerspective(loadedPerspective);
                MessageDialog.openInformation(shell, "Perspective loaded", "Loaded the stored perspective");
            }
        }
    }
}

3.4. Add a handler, command and menu entry for the new handlers

Create commands, handlers and menu entries for your two new handler classes, as you did in earlier exercises.

4. Learn more and get support

This tutorial continues on Eclipse RCP online training or Eclipse IDE extensions with lots of video material, additional exercises and much more content.

Home Tutorials Training Consulting Books Company Contact us


Get more...