| /******************************************************************************* |
| * Copyright (c) 2008 - 2017 Profactor GmbH, TU Wien ACIN, fortiss GmbH |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Gerhard Ebenhofer, Alois Zoitl, Monika Wenger |
| * - initial API and implementation and/or initial documentation |
| *******************************************************************************/ |
| package org.eclipse.fordiac.ide.model.commands.change; |
| |
| import java.util.List; |
| |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.fordiac.ide.model.Palette.FBTypePaletteEntry; |
| import org.eclipse.fordiac.ide.model.Palette.SubApplicationTypePaletteEntry; |
| import org.eclipse.fordiac.ide.model.commands.Messages; |
| import org.eclipse.fordiac.ide.model.commands.create.AbstractConnectionCreateCommand; |
| import org.eclipse.fordiac.ide.model.commands.create.AdapterConnectionCreateCommand; |
| import org.eclipse.fordiac.ide.model.commands.create.CreateSubAppInstanceCommand; |
| import org.eclipse.fordiac.ide.model.commands.create.DataConnectionCreateCommand; |
| import org.eclipse.fordiac.ide.model.commands.create.EventConnectionCreateCommand; |
| import org.eclipse.fordiac.ide.model.commands.create.FBCreateCommand; |
| import org.eclipse.fordiac.ide.model.libraryElement.AdapterDeclaration; |
| import org.eclipse.fordiac.ide.model.libraryElement.AutomationSystem; |
| import org.eclipse.fordiac.ide.model.libraryElement.Connection; |
| import org.eclipse.fordiac.ide.model.libraryElement.Event; |
| import org.eclipse.fordiac.ide.model.libraryElement.FB; |
| import org.eclipse.fordiac.ide.model.libraryElement.FBNetwork; |
| import org.eclipse.fordiac.ide.model.libraryElement.FBNetworkElement; |
| import org.eclipse.fordiac.ide.model.libraryElement.IInterfaceElement; |
| import org.eclipse.fordiac.ide.model.libraryElement.LibraryElementFactory; |
| import org.eclipse.fordiac.ide.model.libraryElement.Mapping; |
| import org.eclipse.fordiac.ide.model.libraryElement.Resource; |
| import org.eclipse.fordiac.ide.model.libraryElement.StructManipulator; |
| import org.eclipse.fordiac.ide.model.libraryElement.SubApp; |
| import org.eclipse.fordiac.ide.model.libraryElement.VarDeclaration; |
| import org.eclipse.fordiac.ide.ui.errormessages.ErrorMessenger; |
| import org.eclipse.gef.commands.Command; |
| import org.eclipse.gef.commands.CompoundCommand; |
| |
| public class MapToCommand extends Command { |
| private final FBNetworkElement srcElement; |
| private final Resource resource; |
| private UnmapCommand unmappFromExistingTarget; |
| private FBNetworkElement targetElement; |
| private final Mapping mapping = LibraryElementFactory.eINSTANCE.createMapping(); |
| private final CompoundCommand createdConnections = new CompoundCommand(); |
| |
| public MapToCommand(final FBNetworkElement srcElement, final Resource resource) { |
| this.srcElement = srcElement; |
| this.resource = resource; |
| } |
| |
| @Override |
| public boolean canExecute() { |
| if (srcElement == null) { |
| return false; |
| } |
| if ((srcElement.isMapped()) && (srcElement.getOpposite().getFbNetwork().equals(resource.getFBNetwork()))) { |
| ErrorMessenger.popUpErrorMessage(Messages.MapToCommand_STATUSMessage_AlreadyMapped); |
| return false; // already mapped to this resource -> nothing to do -> mapping not possible! |
| } |
| |
| final boolean supports = deviceSupportsType(); |
| if (!supports) { |
| ErrorMessenger.popUpErrorMessage(Messages.MapToCommand_STATUSMessage_TypeNotSupported); |
| } |
| return supports; |
| } |
| |
| private boolean deviceSupportsType() { |
| return true; |
| } |
| |
| /** |
| * Steps needed for the mapping command: 1. If already mapped create unmapp |
| * command and execute it 2. Create FB in target FBNetwork (use FBnetwork create |
| * command) 3. Create Mapping entry 4. Determine list of connections that need |
| * to be created in target FBNetwork 5. Execute the create connection command |
| * for these |
| */ |
| @Override |
| public void execute() { |
| if (srcElement.isMapped()) { |
| unmappFromExistingTarget = new UnmapCommand(srcElement.getOpposite()); |
| unmappFromExistingTarget.execute(); |
| } |
| |
| createTargetElement(); |
| |
| mapping.setFrom(srcElement); |
| mapping.setTo(targetElement); |
| srcElement.setMapping(mapping); |
| targetElement.setMapping(mapping); |
| getAutomationSystem().getMapping().add(mapping); |
| |
| checkConnections(); |
| createdConnections.execute(); |
| } |
| |
| /** |
| * Steps 1. handle broken and unbroken connections 2. for each connection create |
| * command -> execute undo 3. for FBcreate command -> execute undo 4. remove |
| * mapping entry 5. if unmapp command is not null -> execute undo |
| */ |
| @Override |
| public void undo() { |
| createdConnections.undo(); |
| |
| srcElement.setMapping(null); // mapping should be removed first so that all notifiers checking for mapped |
| // state will not invalily afterwards use the resource |
| targetElement.setMapping(null); |
| getTargetFBNetwork().getNetworkElements().remove(targetElement); |
| getAutomationSystem().getMapping().remove(mapping); |
| |
| if (null != unmappFromExistingTarget) { |
| unmappFromExistingTarget.undo(); |
| } |
| } |
| |
| /** |
| * Steps 1. if unmapp command is not null -> execute redo 2. for FBcreate |
| * command -> execute redo 3. readd mapping entry 3. for each connection create |
| * command -> execute redo 4. handle broken and unbroken connections |
| */ |
| @Override |
| public void redo() { |
| if (null != unmappFromExistingTarget) { |
| unmappFromExistingTarget.redo(); |
| } |
| getTargetFBNetwork().getNetworkElements().add(targetElement); |
| srcElement.setMapping(mapping); |
| targetElement.setMapping(mapping); |
| getAutomationSystem().getMapping().add(mapping); |
| createdConnections.redo(); |
| } |
| |
| protected void createTargetElement() { |
| if (srcElement instanceof StructManipulator) { |
| targetElement = createTargetStructManipulator(); |
| } else if (srcElement instanceof FB) { |
| targetElement = createTargetFB(); |
| } else if (srcElement instanceof SubApp) { |
| if (null != srcElement.getPaletteEntry()) { |
| targetElement = createTargetTypedSubApp(); |
| } else { |
| targetElement = createTargetUntypedSubApp(); |
| } |
| } |
| targetElement.setName(srcElement.getName()); |
| transferFBParams(); |
| } |
| |
| private FBNetworkElement createTargetFB() { |
| final FBCreateCommand targetCreateFB = new FBCreateCommand((FBTypePaletteEntry) srcElement.getPaletteEntry(), |
| getTargetFBNetwork(), srcElement.getPosition().getX(), srcElement.getPosition().getY()); |
| targetCreateFB.execute(); |
| return targetCreateFB.getFB(); |
| } |
| |
| private FBNetworkElement createTargetStructManipulator() { |
| final StructManipulator manipulator = (StructManipulator) createTargetFB(); |
| manipulator.setStructTypeElementsAtInterface(((StructManipulator) srcElement).getStructType()); |
| return manipulator; |
| } |
| |
| private FBNetworkElement createTargetTypedSubApp() { |
| final CreateSubAppInstanceCommand cmd = new CreateSubAppInstanceCommand( |
| (SubApplicationTypePaletteEntry) srcElement.getPaletteEntry(), getTargetFBNetwork(), |
| srcElement.getPosition().getX(), srcElement.getPosition().getY()); |
| cmd.execute(); |
| return cmd.getSubApp(); |
| } |
| |
| private FBNetworkElement createTargetUntypedSubApp() { |
| final SubApp element = LibraryElementFactory.eINSTANCE.createSubApp(); |
| element.setPosition(EcoreUtil.copy(srcElement.getPosition())); |
| element.setInterface(LibraryElementFactory.eINSTANCE.createInterfaceList()); |
| element.setInterface(EcoreUtil.copy(srcElement.getInterface())); |
| for (final IInterfaceElement ie : element.getInterface().getAllInterfaceElements()) { |
| ie.getInputConnections().clear(); |
| ie.getOutputConnections().clear(); |
| } |
| getTargetFBNetwork().getNetworkElements().add(element); |
| return element; |
| } |
| |
| private void transferFBParams() { |
| final List<VarDeclaration> destInputs = targetElement.getInterface().getInputVars(); |
| final List<VarDeclaration> srcInputs = srcElement.getInterface().getInputVars(); |
| |
| for (int i = 0; i < destInputs.size(); i++) { |
| final VarDeclaration srcVar = srcInputs.get(i); |
| final VarDeclaration dstVar = destInputs.get(i); |
| |
| if ((null != srcVar.getValue()) && (!srcVar.getValue().getValue().isEmpty())) { |
| if (null == dstVar.getValue()) { |
| dstVar.setValue(LibraryElementFactory.eINSTANCE.createValue()); |
| } |
| dstVar.getValue().setValue(srcVar.getValue().getValue()); |
| } |
| } |
| } |
| |
| private AutomationSystem getAutomationSystem() { |
| return srcElement.getFbNetwork().getApplication().getAutomationSystem(); |
| } |
| |
| private void checkConnections() { |
| for (final IInterfaceElement interfaceElement : srcElement.getInterface().getAllInterfaceElements()) { |
| if (interfaceElement.isIsInput()) { |
| checkInputConnections(interfaceElement); |
| } else { |
| checkOutputConnections(interfaceElement); |
| } |
| } |
| } |
| |
| private void checkInputConnections(final IInterfaceElement interfaceElement) { |
| for (final Connection connection : interfaceElement.getInputConnections()) { |
| final Resource res = connection.getSourceElement().getResource(); |
| if (resource.equals(res)) { |
| // we need to create a connection in the target resource |
| addConnectionCreateCommand( |
| connection.getSourceElement().getOpposite() |
| .getInterfaceElement(connection.getSource().getName()), |
| targetElement.getInterfaceElement(interfaceElement.getName())); |
| } |
| } |
| } |
| |
| private void checkOutputConnections(final IInterfaceElement interfaceElement) { |
| for (final Connection connection : interfaceElement.getOutputConnections()) { |
| if (!isSelfConnection(connection)) { // leave self-connection to be handled by the inputs |
| final Resource res = connection.getDestinationElement().getResource(); |
| if (resource.equals(res)) { |
| // we need to create a connection in the target resource |
| final IInterfaceElement destination = connection.getDestinationElement().getOpposite() |
| .getInterfaceElement(connection.getDestination().getName()); |
| addConnectionCreateCommand(targetElement.getInterfaceElement(interfaceElement.getName()), |
| destination); |
| if ((destination instanceof AdapterDeclaration) || (destination instanceof VarDeclaration)) { |
| checkForDeleteConnections(destination); |
| } |
| } |
| } |
| } |
| } |
| |
| private boolean isSelfConnection(final Connection connection) { |
| return connection.getSourceElement() == connection.getDestinationElement(); |
| } |
| |
| private void addConnectionCreateCommand(final IInterfaceElement source, final IInterfaceElement destination) { |
| final AbstractConnectionCreateCommand cmd = getConnectionCreatCMD(source); |
| if (null != cmd) { |
| cmd.setSource(source); |
| cmd.setDestination(destination); |
| createdConnections.add(cmd); |
| } |
| } |
| |
| private void checkForDeleteConnections(final IInterfaceElement destination) { |
| // TODO model refactoring - determine also connection in the target resource |
| // which maybe have to be deleted |
| } |
| |
| private AbstractConnectionCreateCommand getConnectionCreatCMD(final IInterfaceElement interfaceElement) { |
| if (interfaceElement instanceof Event) { |
| return new EventConnectionCreateCommand(resource.getFBNetwork()); |
| } else if (interfaceElement instanceof AdapterDeclaration) { |
| return new AdapterConnectionCreateCommand(resource.getFBNetwork()); |
| } else if (interfaceElement instanceof VarDeclaration) { |
| return new DataConnectionCreateCommand(resource.getFBNetwork()); |
| } |
| return null; |
| } |
| |
| private FBNetwork getTargetFBNetwork() { |
| return resource.getFBNetwork(); |
| } |
| |
| // This code is here to serve as template for handling the connections to be |
| // deleted |
| /* |
| * public void oldExecute() { boolean deletedConnections = false; |
| * |
| * uiResourceEditor.getResourceElement().getFBNetwork().getMappedFBs().add( |
| * mappedFBView.getFb()); |
| * |
| * for (InterfaceElementView interfaceElement : fbView.getInterfaceElements()) { |
| * for (ConnectionView connectionView : interfaceElement.getInConnections()) { |
| * if (connectionView.getSource().eContainer() instanceof FBView) { FBView |
| * sourceFBView = ((FBView) |
| * connectionView.getSource().eContainer()).getMappedFB(); if (sourceFBView != |
| * null && sourceFBView.getFb().getResource() |
| * .equals(uiResourceEditor.getResourceElement().getFBNetwork())) { |
| * ConnectionView newConnection = UiFactory.eINSTANCE.createConnectionView(); |
| * newConnection.setConnectionElement(connectionView.getConnectionElement()); |
| * newConnection.setDestination(connectionView.getDestination(). |
| * getMappedInterfaceElement()); |
| * newConnection.setSource(connectionView.getSource().getMappedInterfaceElement( |
| * )); uiResourceEditor.getConnections().add(newConnection); |
| * ConnectionUtil.addConnectionToResource(newConnection.getConnectionElement(), |
| * uiResourceEditor.getResourceElement()); |
| * connectionView.getConnectionElement().setBrokenConnection(false); |
| * System.out.println("notBroken: " + connectionView); |
| * |
| * for (ConnectionView temp : |
| * connectionView.getSource().getMappedInterfaceElement() .getOutConnections()) |
| * { System.out.println( "Is Resource Connection " + |
| * temp.getConnectionElement().isResourceConnection()); if |
| * (temp.getConnectionElement().isResourceConnection()) { |
| * DeleteConnectionCommand deleteCMD = new DeleteConnectionCommand(temp); |
| * deleteCMD.execute(); deletedConnections = true; } } } else { |
| * System.out.println("isBroken: " + connectionView); |
| * connectionView.getConnectionElement().setBrokenConnection(true); // nothing |
| * to do } } } } if (deletedConnections) { MessageBox informUser = new |
| * MessageBox(Display.getDefault().getActiveShell()); |
| * informUser.setText("Warning"); informUser.setMessage( |
| * "Remapping required deletion of Connections added within the Resource - please check your network" |
| * ); informUser.open(); // TODO check whether markers could be used! } } |
| */ |
| |
| } |