Constructing the Eclipse application model. This tutorial given an introduction how to use 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 do 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 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 orconstruct the application model based on information from a database.

Implementing this interface requires knowledge about 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 - Saving and restoring a perspective of the application model

This exercise implements the option to persist your currently perspective in an external file. This requires, of course, that your application model uses perspectives.

3.1. Add manifest dependencies

Ensure that the following dependencies are entered in the manifest.

  • org.eclipse.emf.ecore

  • org.eclipse.emf.ecore.xmi

3.2. Implement a persistence handler

The following snippet shows a handler implementation. The hander persists the model elements of the active perspective in an xmi file.

The following assumes that you are doing the implementation in a plug-in called com.vogella.rcp.persistence.handlers. Feel free to adjust.

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
        E4XMIResourceFactory e4xmiResourceFactory = new E4XMIResourceFactory();
        Resource resource = e4xmiResourceFactory.createResource(null);

        // You must clone the perspective as snippet, otherwise the running
        // application would break, because the saving process of the resource
        // removes the element from the running application model
        MUIElement clonedPerspective = modelService.cloneElement(activePerspective, window);

        // 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

The created xmi file can be loaded via the load method of the Resource class.

The following snippet is an example, where a stored perspective is applied to an existing application model. In case an existing perspective with the same elementId as the one of the loaded perspective is found, it is removed. Afterwards the code adds and switches to the loaded perspective.

package com.vogella.rcp.persistence.handlers;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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.basic.MWindow;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
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 ConstructPerspectiveFromExternalSource {

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

        // create a resource, which is able to store e4 model elements
        @SuppressWarnings("restriction")
        E4XMIResourceFactory e4xmiResourceFactory = new E4XMIResourceFactory();
        @SuppressWarnings("restriction")
        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.
                MPerspective activePerspective = modelService.getActivePerspective(window);
                MElementContainer<MUIElement> perspectiveParent = activePerspective.getParent();

                // remove the current perspective, 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);

                partService.switchPerspective(loadedPerspective);
                MessageDialog.openInformation(shell, "Perspective resetted", "Resetted perspective");
            }
        }
    }
}

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.