/**
* 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.core.graphiti.sad.ui.modelmap;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.impl.CreateContext;
import gov.redhawk.core.graphiti.sad.ui.GraphitiSadUIPlugin;
import gov.redhawk.core.graphiti.sad.ui.diagram.feature.ComponentCreateFeature;
import gov.redhawk.core.graphiti.ui.editor.AbstractGraphitiMultiPageEditor;
import gov.redhawk.core.graphiti.ui.modelmap.AbstractGraphitiModelMap;
import gov.redhawk.core.graphiti.ui.modelmap.CreateComponentInstantiationCommand;
import gov.redhawk.model.sca.CorbaObjWrapper;
import gov.redhawk.model.sca.ScaComponent;
import gov.redhawk.model.sca.ScaConnection;
import gov.redhawk.model.sca.ScaPort;
import gov.redhawk.model.sca.ScaPortContainer;
import gov.redhawk.model.sca.ScaPropertyContainer;
import gov.redhawk.model.sca.ScaProvidesPort;
import gov.redhawk.model.sca.ScaWaveform;
import gov.redhawk.model.sca.util.ReleaseJob;
import gov.redhawk.sca.util.SubMonitor;
import mil.jpeojtrs.sca.partitioning.ComponentInstantiation;
import mil.jpeojtrs.sca.partitioning.ConnectionTarget;
import mil.jpeojtrs.sca.partitioning.ProvidesPortStub;
import mil.jpeojtrs.sca.partitioning.UsesPortStub;
import mil.jpeojtrs.sca.sad.SadComponentInstantiation;
import mil.jpeojtrs.sca.spd.SoftPkg;
public class GraphitiSADModelMap extends AbstractGraphitiModelMap {
private final ScaWaveform waveform;
/**
* Associates {@link ScaComponent}s with their {@link SadComponentInstantiation}.
*/
private final Map<String, SADNodeMapEntry> nodes = Collections.synchronizedMap(new HashMap<String, SADNodeMapEntry>());
public GraphitiSADModelMap(final AbstractGraphitiMultiPageEditor editor, final ScaWaveform waveform) {
super(editor);
Assert.isNotNull(waveform, "Sandbox Waveform must not be null");
this.waveform = waveform;
}
public ScaWaveform getWaveform() {
return waveform;
}
protected Map<String, SADNodeMapEntry> getNodes() {
return nodes;
}
////////////////////////////////////////////////////
// Components section
////////////////////////////////////////////////////
/**
* Called when a new {@link ScaComponent} is added to the SCA model. Asynchronously updates the diagram.
* @param comp
*/
public void add(final ScaComponent comp) {
final SADNodeMapEntry nodeMapEntry = new SADNodeMapEntry();
nodeMapEntry.setScaComponent(comp);
synchronized (nodes) {
if (nodes.get(nodeMapEntry.getKey()) != null) {
return;
} else {
nodes.put(nodeMapEntry.getKey(), nodeMapEntry);
}
}
Job job = new Job("Adding component: " + comp.getInstantiationIdentifier()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
SubMonitor subMonitor = SubMonitor.convert(monitor, 1);
SadComponentInstantiation newComp = null;
try {
newComp = (SadComponentInstantiation) GraphitiSADModelMap.this.create(comp, subMonitor.newChild(1));
nodeMapEntry.setProfile(newComp);
reflectRuntimeStatus();
return Status.OK_STATUS;
} catch (CoreException e) {
nodes.remove(nodeMapEntry.getKey());
return new Status(IStatus.ERROR, GraphitiSadUIPlugin.PLUGIN_ID, "Failed to add component " + comp.getInstantiationIdentifier(), e);
} finally {
if (nodes.get(nodeMapEntry.getKey()) == null) {
delete(newComp);
}
subMonitor.done();
}
}
};
job.schedule();
}
/**
* Called when a new {@link SadComponentInstantiation} is added to the diagram's XML model. Asynchronously launches
* the component.
* @param compInst
*/
public void add(final SadComponentInstantiation compInst) {
// Launching not supported by this class
throw new IllegalStateException("Launching components is not permitted by this class");
}
protected CreateComponentInstantiationCommand createComponentInstantiationCommand(TransactionalEditingDomain editingDomain,
final IFeatureProvider featureProvider, ScaPropertyContainer< ? , SoftPkg> newObject) {
final ScaComponent newComponent = (ScaComponent) newObject;
return new CreateComponentInstantiationCommand(editingDomain) {
private ComponentInstantiation compInst;
@Override
public ComponentInstantiation getComponentInstantiation() {
return compInst;
}
@Override
protected void doExecute() {
ComponentCreateFeature createComponentFeature = new ComponentCreateFeature(featureProvider, newComponent.getProfileObj(), null);
CreateContext createContext = new CreateContext();
createContext.putProperty(ComponentCreateFeature.OVERRIDE_USAGE_NAME, newComponent.getName());
createContext.putProperty(ComponentCreateFeature.OVERRIDE_INSTANTIATION_ID, newComponent.getInstantiationIdentifier());
createContext.setTargetContainer(featureProvider.getDiagramTypeProvider().getDiagram());
final Object[] objects = createComponentFeature.create(createContext);
compInst = (ComponentInstantiation) objects[0];
}
};
}
protected UsesPortStub findSource(ScaConnection newValue) {
final SadComponentInstantiation sourceComponent = getComponentInstantiation((ScaComponent) newValue.getPort().eContainer());
if (sourceComponent == null) {
return null;
}
for (final UsesPortStub stub : sourceComponent.getUses()) {
if (stub.getName() != null && stub.getName().equals(newValue.getPort().getName())) {
return stub;
}
}
return null;
}
protected ConnectionTarget findTarget(ScaConnection newValue) {
// Iterate port containers looking for a provides ports which may match
List<ScaComponent> components = this.waveform.getComponentsCopy();
for (final ScaComponent portContainer : components) {
if (!portContainer.isSetPorts()) {
portContainer.fetchPorts(null);
}
for (final ScaPort< ? , ? > port : portContainer.getPorts()) {
if (port instanceof ScaProvidesPort && port.getObj()._is_equivalent(newValue.getData().port)) {
final SadComponentInstantiation compInst = getComponentInstantiation(portContainer);
if (compInst == null) {
continue;
}
for (final ProvidesPortStub provides : compInst.getProvides()) {
if (provides.getName().equals(port.getName())) {
return provides;
}
}
}
}
}
// Iterate anything that could be a component supported interface looking for a match
for (final ScaComponent csiTarget : components) {
if (csiTarget.getObj()._is_equivalent(newValue.getData().port)) {
SadComponentInstantiation compInst = getComponentInstantiation(csiTarget);
if (compInst != null) {
return compInst.getInterfaceStub();
}
break;
}
}
return null;
}
/* package */ SadComponentInstantiation getComponentInstantiation(final ScaComponent comp) {
if (comp == null) {
return null;
}
SADNodeMapEntry nodeMapEntry = nodes.get(SADNodeMapEntry.getKey(comp));
if (nodeMapEntry != null) {
return nodeMapEntry.getProfile();
} else {
return null;
}
}
private ScaComponent get(final ComponentInstantiation compInst) {
if (compInst == null) {
return null;
}
SADNodeMapEntry nodeMapEntry = nodes.get(SADNodeMapEntry.getKey(compInst));
if (nodeMapEntry != null) {
return nodeMapEntry.getScaComponent();
} else {
return null;
}
}
protected CorbaObjWrapper< ? > getCorbaObjWrapper(ComponentInstantiation compInst) {
return get(compInst);
}
protected ScaPortContainer getPortContainer(ComponentInstantiation portContainer) {
return get(portContainer);
}
/**
* Adds a mapping between the SCA model object and diagram XML model object
* @param comp
* @param inst
*/
public void put(ScaComponent comp, SadComponentInstantiation inst) {
SADNodeMapEntry nodeMapEntry = new SADNodeMapEntry(comp, inst);
nodes.put(nodeMapEntry.getKey(), nodeMapEntry);
}
/**
* Called when an existing {@link ScaComponent} is removed from the SCA model. Removes the PictogramElement from the
* diagram.
* @param comp
*/
public void remove(final ScaComponent comp) {
final SADNodeMapEntry nodeMapEntry = nodes.remove(SADNodeMapEntry.getKey(comp));
if (nodeMapEntry == null) {
return;
}
final SadComponentInstantiation oldComp = nodeMapEntry.getProfile();
if (oldComp != null) {
delete(oldComp);
}
}
/**
* Called when a {@link SadComponentInstantiation} is removed from the diagram's XML model. Asynchronously triggers
* a call to <code>releaseObject()</code>.
* @param compInst
*/
public void remove(final SadComponentInstantiation compInst) {
if (compInst == null) {
return;
}
final SADNodeMapEntry nodeMapEntry = nodes.remove(SADNodeMapEntry.getKey(compInst));
if (nodeMapEntry == null) {
return;
}
final ScaComponent oldComp = nodeMapEntry.getScaComponent();
if (oldComp != null) {
Job releaseJob = new ReleaseJob(oldComp);
releaseJob.schedule();
}
}
////////////////////////////////////////////////////
// Reflecting status
////////////////////////////////////////////////////
/**
* Updates the pictogram element's start/stop state.
* @param scaComponent
* @param started
*/
public void startStopComponent(ScaComponent scaComponent, final Boolean started) {
final boolean resolveStarted = (started == null) ? false : started;
final SADNodeMapEntry nodeMapEntry = nodes.get(SADNodeMapEntry.getKey(scaComponent));
if (nodeMapEntry == null) {
return;
}
final ComponentInstantiation componentInstantiation = nodeMapEntry.getProfile();
if (componentInstantiation != null) {
updateStateStopState(componentInstantiation, resolveStarted);
}
}
/**
* Updates pictogram elements to reflect runtime status.
*/
public void reflectRuntimeStatus() {
synchronized (nodes) {
for (String nodeKey : nodes.keySet()) {
final SADNodeMapEntry nodeMapEntry = nodes.get(nodeKey);
ScaComponent component = nodeMapEntry.getScaComponent();
if (component == null) {
updateEnabledState(nodeMapEntry.getProfile(), false);
} else {
updateEnabledState(nodeMapEntry.getProfile(), true);
startStopComponent(component, component.getStarted());
}
}
}
}
/**
* Updates the pictogram element's {@link IStatus}.
* @param scaComponent
* @param status
*/
public void reflectErrorState(ScaComponent scaComponent, final IStatus status) {
final SADNodeMapEntry nodeMapEntry = nodes.get(SADNodeMapEntry.getKey(scaComponent));
if (nodeMapEntry == null) {
return;
}
final ComponentInstantiation componentInstantiation = nodeMapEntry.getProfile();
if (componentInstantiation != null) {
updateErrorState(componentInstantiation, status);
}
}
}