/******************************************************************************* * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * 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 gov.redhawk.ide.graphiti.sad.ui.diagram.patterns; import gov.redhawk.core.graphiti.ui.diagram.patterns.AbstractPortSupplierPattern; import gov.redhawk.core.graphiti.ui.ext.RHContainerShape; import gov.redhawk.core.graphiti.ui.util.StyleUtil; import gov.redhawk.ide.graphiti.ui.diagram.features.custom.IDialogEditingPattern; import gov.redhawk.ide.graphiti.ui.diagram.providers.ImageProvider; import gov.redhawk.ide.graphiti.ui.diagram.util.DUtil; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import mil.jpeojtrs.sca.partitioning.ComponentSupportedInterfaceStub; import mil.jpeojtrs.sca.partitioning.DeviceUsedByApplication; import mil.jpeojtrs.sca.partitioning.PartitioningFactory; import mil.jpeojtrs.sca.partitioning.ProvidesPortStub; import mil.jpeojtrs.sca.partitioning.UsesDeviceStub; import mil.jpeojtrs.sca.partitioning.UsesPortStub; import mil.jpeojtrs.sca.sad.SadConnectInterface; import mil.jpeojtrs.sca.sad.SoftwareAssembly; import mil.jpeojtrs.sca.sad.UsesDeviceDependencies; import mil.jpeojtrs.sca.spd.PropertyRef; import mil.jpeojtrs.sca.spd.UsesDevice; import org.eclipse.core.databinding.validation.IValidator; import org.eclipse.core.databinding.validation.ValidationStatus; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.TransactionalCommandStack; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.graphiti.features.context.IAddContext; import org.eclipse.graphiti.features.context.ICreateContext; import org.eclipse.graphiti.features.context.ICustomContext; import org.eclipse.graphiti.features.context.IDeleteContext; import org.eclipse.graphiti.features.context.IDirectEditingContext; import org.eclipse.graphiti.features.context.IMoveShapeContext; import org.eclipse.graphiti.features.context.IResizeShapeContext; import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.mm.pictograms.Shape; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.ui.PlatformUI; import ExtendedCF.WKP.DEVICEKIND; import FRONTEND.FE_TUNER_DEVICE_KIND; public abstract class AbstractUsesDevicePattern extends AbstractPortSupplierPattern implements IDialogEditingPattern { public AbstractUsesDevicePattern() { super(null); } // THE FOLLOWING THREE METHODS DETERMINE IF PATTERN IS APPLICABLE TO OBJECT public abstract boolean isMainBusinessObjectApplicable(Object mainBusinessObject); @Override protected boolean isPatternControlled(PictogramElement pictogramElement) { Object domainObject = getBusinessObjectForPictogramElement(pictogramElement); return isMainBusinessObjectApplicable(domainObject); } @Override protected boolean isPatternRoot(PictogramElement pictogramElement) { Object domainObject = getBusinessObjectForPictogramElement(pictogramElement); return isMainBusinessObjectApplicable(domainObject); } // DIAGRAM FEATURES @Override public boolean canAdd(IAddContext context) { if (context.getNewObject() instanceof UsesDeviceStub) { if (context.getTargetContainer() instanceof Diagram) { return true; } } return false; } @Override public boolean canMoveShape(IMoveShapeContext context) { if (!super.canMoveShape(context)) { return false; } GraphicsAlgorithm ga = context.getShape().getGraphicsAlgorithm(); if (DUtil.overlapsHostCollocation(getDiagram(), ga.getWidth(), ga.getHeight(), context.getX(), context.getY())) { return false; } return true; } @Override protected String getOuterTitle(EObject obj) { if (obj instanceof UsesDeviceStub) { return getOuterTitle((UsesDeviceStub) obj); } return null; } /** * Provides the title of the outer shape * @param usesDeviceStub * @return */ public String getOuterTitle(UsesDeviceStub usesDeviceStub) { return getCreateName(); } @Override protected String getInnerTitle(EObject obj) { if (obj instanceof UsesDeviceStub) { return getInnerTitle((UsesDeviceStub) obj); } return null; } public String getInnerTitle(UsesDeviceStub usesDeviceStub) { return usesDeviceStub.getUsesDevice().getId(); } protected void setInnerTitle(EObject businessObject, String value) { UsesDeviceStub usesDeviceStub = (UsesDeviceStub) businessObject; usesDeviceStub.getUsesDevice().setId(value); } @Override public boolean canCreate(ICreateContext context) { return context.getTargetContainer() instanceof Diagram; } @Override public abstract Object[] create(ICreateContext context); @Override public boolean canResizeShape(IResizeShapeContext context) { return true; } @Override public boolean canDelete(IDeleteContext context) { Object obj = DUtil.getBusinessObject(context.getPictogramElement()); if (obj instanceof UsesDeviceStub) { return true; } return super.canDelete(context); } @Override public void delete(IDeleteContext context) { // set UsesDeviceStub to delete final UsesDeviceStub usesDeviceStub = (UsesDeviceStub) DUtil.getBusinessObject(context.getPictogramElement()); // get sad from diagram final SoftwareAssembly sad = DUtil.getDiagramSAD(getDiagram()); // editing domain for our transaction TransactionalEditingDomain editingDomain = getFeatureProvider().getDiagramTypeProvider().getDiagramBehavior().getEditingDomain(); // Perform business object manipulation in a Command TransactionalCommandStack stack = (TransactionalCommandStack) editingDomain.getCommandStack(); stack.execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { //remove device connections deleteUsesDeviceStubConnections(usesDeviceStub, sad); //remove device for (Iterator<UsesDevice> iter = sad.getUsesDeviceDependencies().getUsesdevice().iterator(); iter.hasNext();) { UsesDevice s = iter.next(); if (usesDeviceStub.getUsesDevice().getId().equals(s.getId())) { iter.remove(); } } //remove usesdevicedependencies if there are none left if (sad.getUsesDeviceDependencies().getUsesdevice().size() < 1) { EcoreUtil.delete(sad.getUsesDeviceDependencies()); } } }); PictogramElement pe = context.getPictogramElement(); Object[] businessObjects = getFeatureProvider().getAllBusinessObjectsForPictogramElement(pe); preDelete(context); if (businessObjects != null) { for (Object bo : businessObjects) { if (bo instanceof EObject) { EcoreUtil.delete((EObject) bo, true); } } } postDelete(context); super.delete(context); } private void deleteUsesDeviceStubConnections(UsesDeviceStub usesDeviceStubToDelete, SoftwareAssembly sad) { // find and remove any attached connections // gather connections List<SadConnectInterface> connectionsToRemove = new ArrayList<SadConnectInterface>(); if (sad.getConnections() == null) { return; } for (SadConnectInterface connection : sad.getConnections().getConnectInterface()) { if (connection.getProvidesPort() != null && connection.getProvidesPort().getDeviceUsedByApplication() != null && connection.getProvidesPort().getDeviceUsedByApplication().getUsesRefId().equals(usesDeviceStubToDelete.getUsesDevice().getId())) { connectionsToRemove.add(connection); } else if (connection.getComponentSupportedInterface() != null && connection.getComponentSupportedInterface().getDeviceUsedByApplication() != null && connection.getComponentSupportedInterface().getDeviceUsedByApplication().getUsesRefId().equals(usesDeviceStubToDelete.getUsesDevice().getId())) { connectionsToRemove.add(connection); } else if (connection.getUsesPort().getDeviceUsedByApplication() != null && connection.getUsesPort().getDeviceUsedByApplication().getUsesRefId().equals(usesDeviceStubToDelete.getUsesDevice().getId())) { connectionsToRemove.add(connection); } } // remove gathered connections if (sad.getConnections() != null) { sad.getConnections().getConnectInterface().removeAll(connectionsToRemove); } } @Override public String checkValueValid(String value, IDirectEditingContext context) { return super.checkValueValid(value, context); } @Override protected String getOuterImageId() { return ImageProvider.IMG_FIND_BY; } @Override protected String getInnerImageId() { return ImageProvider.IMG_USES_DEVICE_FRONTEND_TUNER; } @Override protected String getStyleForOuter() { return StyleUtil.OUTER_SHAPE; } @Override protected String getStyleForInner() { return StyleUtil.USES_DEVICE_INNER; } @Override protected List<EObject> getBusinessObjectsToLink(EObject obj) { List<EObject> businessObjectsToLink = new ArrayList<EObject>(); businessObjectsToLink.add(obj); return businessObjectsToLink; } @Override protected EList<UsesPortStub> getUses(EObject obj) { if (obj instanceof UsesDeviceStub) { return ((UsesDeviceStub) obj).getUsesPortStubs(); } return null; } @Override protected EList<ProvidesPortStub> getProvides(EObject obj) { if (obj instanceof UsesDeviceStub) { return ((UsesDeviceStub) obj).getProvidesPortStubs(); } return null; } @Override protected ComponentSupportedInterfaceStub getInterface(EObject obj) { if (obj instanceof UsesDeviceStub) { return ((UsesDeviceStub) obj).getInterface(); } return null; } @Override public boolean canDialogEdit(ICustomContext context) { PictogramElement[] pes = context.getPictogramElements(); if (pes != null && pes.length == 1) { return isMainBusinessObjectApplicable(getBusinessObjectForPictogramElement(pes[0])); } return false; } @Override public boolean dialogEdit(ICustomContext context) { RHContainerShape usesDeviceShape = (RHContainerShape) context.getPictogramElements()[0]; final UsesDeviceStub usesDevice = (UsesDeviceStub) getBusinessObjectForPictogramElement(usesDeviceShape); if (editUsesDevice(usesDevice, usesDeviceShape)) { updatePictogramElement(usesDeviceShape); layoutPictogramElement(usesDeviceShape); return true; } else { return false; } } protected abstract boolean editUsesDevice(UsesDeviceStub usesDevice, RHContainerShape usesDeviceShape); protected <E extends Wizard> E openWizard(E wizard) { WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), wizard); if (dialog.open() == WizardDialog.CANCEL) { return null; } return wizard; } /** * Return true if containerShape is linked to UsesDeviceStub * @param containerShape * @return */ public static boolean isUsesDeviceStubShape(ContainerShape containerShape) { if (containerShape instanceof RHContainerShape) { Object obj = DUtil.getBusinessObject(containerShape, UsesDeviceStub.class); if (obj != null && obj instanceof UsesDeviceStub) { return true; } } return false; } /** * Returns all containerShapes linked to UsesDeviceStub * @param containerShape * @return */ public static List<RHContainerShape> getAllUsesDeviceStubShapes(ContainerShape containerShape) { List<RHContainerShape> children = new ArrayList<RHContainerShape>(); if (containerShape instanceof RHContainerShape && isUsesDeviceStubShape(containerShape)) { children.add((RHContainerShape) containerShape); } else { for (Shape s : containerShape.getChildren()) { if (s instanceof ContainerShape) { children.addAll(getAllUsesDeviceStubShapes((ContainerShape) s)); } } } return children; } /** * Create UsesDeviceStrub from UsesDevice * Initializes componentSupportedInterface, be sure to set ports afterwards if applicable * @param usesDevice * @return */ public static UsesDeviceStub createUsesDeviceStub(UsesDevice usesDevice) { UsesDeviceStub usesDeviceStrub = PartitioningFactory.eINSTANCE.createUsesDeviceStub(); usesDeviceStrub.setUsesDevice(usesDevice); usesDeviceStrub.setInterface(PartitioningFactory.eINSTANCE.createComponentSupportedInterfaceStub()); return usesDeviceStrub; } /** * Returns true if the deviceUsedByApplication's usesref id matches the device id of usesDeviceStub * @param deviceUsedByApplication * @param usesDeviceStub * @return */ public static boolean doDeviceUsedByApplicationObjectsMatch(DeviceUsedByApplication deviceUsedByApplication, UsesDeviceStub usesDeviceStub) { if (deviceUsedByApplication.getUsesRefId().equals(usesDeviceStub.getUsesDevice().getId())) { return true; } return false; } /** * Search for the UsesDeviceStub in the diagram given the DeviceUsedByApplication object * @param findBy * @param diagram * @return */ public static UsesDeviceStub findUsesDeviceStub(DeviceUsedByApplication deviceUsedByApplication, List<UsesDeviceStub> usesDeviceStubs) { for (UsesDeviceStub usesDeviceStub : usesDeviceStubs) { if (AbstractUsesDevicePattern.doDeviceUsedByApplicationObjectsMatch(deviceUsedByApplication, usesDeviceStub)) { // it matches return usesDeviceStub; } } return null; } /** * Returns matching UsesDeviceStub for provided DeviceUsedByApplication * @param deviceUsedByApplication * @param containerShape - diagram * @return */ public static UsesDeviceStub findUsesDeviceStub(DeviceUsedByApplication deviceUsedByApplication, ContainerShape containerShape) { for (RHContainerShape usesDeviceStubShape: getAllUsesDeviceStubShapes(containerShape)) { UsesDeviceStub usesDeviceStub = (UsesDeviceStub) DUtil.getBusinessObject(usesDeviceStubShape); if (doDeviceUsedByApplicationObjectsMatch(deviceUsedByApplication, usesDeviceStub)) { return usesDeviceStub; } } return null; } /** * Return true if the proposedId is unique device in the sad file * @param sad * @param proposedDeviceId * @return */ public static boolean isUsesDeviceIdUnique(SoftwareAssembly sad, String existingId, String proposedDeviceId) { if (existingId.equals(proposedDeviceId)) { //if existing name return true; return true; } UsesDeviceDependencies usesDeviceDependencies = sad.getUsesDeviceDependencies(); if (usesDeviceDependencies == null || usesDeviceDependencies.getUsesdevice().size() < 1) { return true; } for (UsesDevice usesDevice: usesDeviceDependencies.getUsesdevice()) { if (usesDevice.getId().equals(proposedDeviceId)) { return false; } } return true; } /** * Create unique device id from provided prefix * @param sad * @param idPrefix * @return */ public static String getUniqueUsesDeviceId(SoftwareAssembly sad, String idPrefix) { int suffixNum = 1; String proposedDeviceId = idPrefix + String.valueOf(suffixNum); UsesDeviceDependencies usesDeviceDependencies = sad.getUsesDeviceDependencies(); if (usesDeviceDependencies == null || usesDeviceDependencies.getUsesdevice().size() < 1) { return proposedDeviceId; } while (true) { boolean found = false; for (UsesDevice usesDevice: usesDeviceDependencies.getUsesdevice()) { if (usesDevice.getId().equals(proposedDeviceId)) { found = true; break; } } if (found) { suffixNum++; proposedDeviceId = idPrefix + String.valueOf(suffixNum); } else { break; } } return proposedDeviceId; } /** * Return true if device is FrontEnd Tuner * @param usesDevice * @return */ public static boolean isFrontEndDevice(UsesDevice usesDevice) { for (PropertyRef refs: usesDevice.getPropertyRef()) { if (DEVICEKIND.value.equals(refs.getRefId()) && FE_TUNER_DEVICE_KIND.value.equals(refs.getValue())) { return true; } } return false; } //Device must not be blank and be unique within sad public static class UsesDeviceIdValidator implements IValidator { private SoftwareAssembly sad; private String existingId; public UsesDeviceIdValidator(SoftwareAssembly sad, String existingId) { this.sad = sad; this.existingId = existingId; } public IStatus validate(Object value) { if ("".equals(value)) { return ValidationStatus.error("Device ID must not be null"); } else if (!AbstractUsesDevicePattern.isUsesDeviceIdUnique(sad, existingId, (String) value)) { return ValidationStatus.error("Device ID must be unique"); } return Status.OK_STATUS; } } /** * Return true if connection involves uses device * @param connectInterface * @return */ public static boolean isUsesDeviceConnection(SadConnectInterface connectInterface) { boolean isUsesDeviceConnection = false; if ((connectInterface.getComponentSupportedInterface() != null && connectInterface.getComponentSupportedInterface().getDeviceUsedByApplication() != null) || (connectInterface.getProvidesPort() != null && connectInterface.getProvidesPort().getDeviceUsedByApplication() != null) || (connectInterface.getUsesPort() != null && connectInterface.getUsesPort().getDeviceUsedByApplication() != null)) { isUsesDeviceConnection = true; } return isUsesDeviceConnection; } }