ac.soton.multisim.ui.policies.ComponentCreateCommand.java Source code

Java tutorial

Introduction

Here is the source code for ac.soton.multisim.ui.policies.ComponentCreateCommand.java

Source

/*
 * Copyright (c) 2014 University of Southampton.
 * 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
 */
package ac.soton.multisim.ui.policies;

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

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eventb.core.basis.MachineRoot;
import org.eventb.emf.core.AbstractExtension;
import org.eventb.emf.core.EventBElement;
import org.eventb.emf.core.machine.Machine;
import org.eventb.emf.persistence.EMFRodinDB;
import org.ptolemy.fmi.FMIModelDescription;
import org.ptolemy.fmi.FMIScalarVariable;
import org.ptolemy.fmi.FMIScalarVariable.Causality;
import org.ptolemy.fmi.FMUFile;

import ac.soton.multisim.Component;
import ac.soton.multisim.ComponentDiagram;
import ac.soton.multisim.FMUComponent;
import ac.soton.multisim.FMUPort;
import ac.soton.multisim.MultisimFactory;
import ac.soton.multisim.MultisimPackage;
import ac.soton.multisim.Port;
import ac.soton.multisim.VariableCausality;
import ac.soton.multisim.ui.DisplayUtil;
import ac.soton.multisim.ui.wizards.pages.EventBImportWizard;
import ac.soton.multisim.util.FMUResource;
import ac.soton.multisim.util.SimulationUtil;

/**
 * Creates component based on the provided element.
 * 
 * Customised from the generated GMF diagram.edit.commands.XXXCreateCommand
 */
public class ComponentCreateCommand extends EditElementCommand {

    private Object element;

    /**
     * @generated
     */
    private ComponentCreateCommand(CreateElementRequest req) {
        super(req.getLabel(), null, req);
    }

    public ComponentCreateCommand(CreateElementRequest createElementRequest, Object element) {
        this(createElementRequest);
        this.element = element;
    }

    /**
     * FIXME: replace with setElementToEdit()
     * @generated
     */
    protected EObject getElementToEdit() {
        EObject container = ((CreateElementRequest) getRequest()).getContainer();
        if (container instanceof View) {
            container = ((View) container).getElement();
        }
        return container;
    }

    /**
     * @generated
     */
    public boolean canExecute() {
        return true;

    }

    /**
     * @generated
     */
    protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info)
            throws ExecutionException {
        Component newElement = createNewElement();
        if (newElement == null)
            return CommandResult.newCancelledCommandResult();

        ComponentDiagram owner = (ComponentDiagram) getElementToEdit();
        owner.getComponents().add(newElement);

        doConfigure(newElement, monitor, info);

        ((CreateElementRequest) getRequest()).setNewElement(newElement);
        return CommandResult.newOKCommandResult(newElement);
    }

    /**
     * @generated
     */
    protected void doConfigure(Component newElement, IProgressMonitor monitor, IAdaptable info)
            throws ExecutionException {
        IElementType elementType = ((CreateElementRequest) getRequest()).getElementType();
        ConfigureRequest configureRequest = new ConfigureRequest(getEditingDomain(), newElement, elementType);
        configureRequest.setClientContext(((CreateElementRequest) getRequest()).getClientContext());
        configureRequest.addParameters(getRequest().getParameters());
        ICommand configureCommand = elementType.getEditCommand(configureRequest);
        if (configureCommand != null && configureCommand.canExecute()) {
            configureCommand.execute(monitor, info);
        }
    }

    /**
     * Creates a new component element.
     * 
     * @return
     * @throws ExecutionException if existing element is not supported for creating a component from
     */
    private Component createNewElement() throws ExecutionException {
        if (element instanceof Component)
            return EcoreUtil.copy((Component) element);
        else if (element instanceof MachineRoot)
            return getEventBComponent((MachineRoot) element);
        else if (element instanceof FMUResource)
            return getFMUComponent((FMUResource) element);

        //XXX shoudln't happen
        throw new ExecutionException("Undefined element");
    }

    /**
     * Returns an FMU component from an FMU resource wrapper.
     * 
     * @param fmu
     * @return
     */
    private Component getFMUComponent(FMUResource fmu) {
        return importFMUComponent(fmu.getFile());
    }

    /**
     * Returns an Event-B component from a machine root.
     * 
     * @param root
     * @return
     */
    private Component getEventBComponent(MachineRoot root) {
        EventBElement machine = EMFRodinDB.INSTANCE.loadEventBComponent(root);

        // check if already defined in the machine
        for (AbstractExtension extension : machine.getExtensions()) {
            if (MultisimPackage.EXTENSION_ID.equals(extension.getExtensionId())) {
                return (Component) EcoreUtil.copy(extension);
            }
        }

        return importEventBComponent((Machine) machine);
    }

    /**
     * Imports Event-B component from a Machine via configuration wizard.
     * 
     * @param machine
     * @return
     */
    private Component importEventBComponent(Machine machine) {
        Shell shell = Display.getCurrent().getActiveShell();
        EventBImportWizard wiz = new EventBImportWizard(machine);
        wiz.init(PlatformUI.getWorkbench(), null);
        WizardDialog wd = new WizardDialog(shell, wiz);
        wd.create();

        Rectangle bounds = DisplayUtil.inchToDisplay(shell, 5, 5);
        wd.getShell().setLocation(bounds.x, bounds.y);
        wd.getShell().setSize(bounds.width, bounds.height);

        if (wd.open() != Window.OK)
            return null;

        return wiz.getComponent();
    }

    /**
     * Imports FMU component from a system File.
     * 
     * @param fmuFile
     * @return
     */
    private Component importFMUComponent(File fmuFile) {
        FMIModelDescription modelDescription;
        try {
            modelDescription = FMUFile.parseFMUFile(fmuFile.getAbsolutePath());
            if (Double.parseDouble(modelDescription.fmiVersion) != 1d)
                throw new IOException("Wrong FMI version");
        } catch (IOException e) {
            e.printStackTrace();
            Display.getCurrent().asyncExec(new Runnable() {
                @Override
                public void run() {
                    MessageDialog.openError(Display.getCurrent().getActiveShell(), "FMU Import Error",
                            "FMU file cannot be parsed.\n"
                                    + "Check wether it is corrupt or not supported: only FMI 1.0 for Co-simulation files are supported for import.");
                }
            });
            return null;
        }

        FMUComponent component = MultisimFactory.eINSTANCE.createFMUComponent();
        component.setName(modelDescription.modelName);
        component.setPath(fmuFile.getAbsolutePath());

        for (FMIScalarVariable scalarVariable : modelDescription.modelVariables) {
            if (scalarVariable.causality == Causality.input) {
                createFMUInput(scalarVariable, component);
            } else if (scalarVariable.causality == Causality.output) {
                createFMUOutput(scalarVariable, component);
            }
        }

        return component;
    }

    /**
     * Creates and appends to component an FMU input port.
     * 
     * @param scalarVariable
     * @param component
     */
    private void createFMUInput(FMIScalarVariable scalarVariable, FMUComponent component) {
        FMUPort variable = MultisimFactory.eINSTANCE.createFMUPort();
        variable.setName(scalarVariable.name);
        variable.setType(SimulationUtil.fmiGetType(scalarVariable));
        variable.setCausality(VariableCausality.INPUT);
        variable.setComment(scalarVariable.description);
        component.getInputs().add((Port) variable);
    }

    /**
     * Creates and appends to component an FMU output port.
     * 
     * @param scalarVariable
     * @param component
     */
    private void createFMUOutput(FMIScalarVariable scalarVariable, FMUComponent component) {
        FMUPort variable = MultisimFactory.eINSTANCE.createFMUPort();
        variable.setName(scalarVariable.name);
        variable.setType(SimulationUtil.fmiGetType(scalarVariable));
        variable.setCausality(VariableCausality.OUTPUT);
        variable.setComment(scalarVariable.description);
        component.getOutputs().add((Port) variable);
    }

}