/**
* 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.model.sca.commands;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.omg.CORBA.SystemException;
import CF.Device;
import CF.ExecutableDeviceHelper;
import CF.LoadableDeviceHelper;
import gov.redhawk.model.sca.ScaDevice;
import gov.redhawk.model.sca.ScaDeviceManager;
import gov.redhawk.model.sca.ScaFactory;
import gov.redhawk.model.sca.ScaPackage;
/**
* Used when updating the devices belonging to a device manager
*
* @since 20.4
*/
public class ScaDeviceManagerMergeDevicesCommand extends SetStatusCommand<ScaDeviceManager> {
protected static class DeviceData {
private final Device deviceObject;
private final EClass deviceType;
public DeviceData(Device dev, EClass deviceType) {
super();
this.deviceObject = dev;
this.deviceType = deviceType;
}
}
private final Map<String, DeviceData> rootDevices;
private final Map<String, DeviceData> childDevices;
/**
* Creates an EMF command which will update a device manager's devices based on data from a CORBA call.
* <p/>
* Note that this method narrows CORBA objects, and makes CORBA calls to the device, and therefore may block.
*
* @param provider The device manager to update
* @param devices The information from a CORBA call about the device manager's registered devices
* @param status The status from having fetched CORBA data
*/
public ScaDeviceManagerMergeDevicesCommand(ScaDeviceManager provider, Device[] devices, IStatus status) {
super(provider, ScaPackage.Literals.SCA_DEVICE_MANAGER__DEVICES, status);
rootDevices = new HashMap<>();
childDevices = new HashMap<>();
for (Device device : devices) {
String ior = device.toString();
DeviceData data = getDeviceData(device);
try {
if (device.compositeDevice() == null) {
rootDevices.put(ior, data);
} else {
childDevices.put(ior, data);
}
} catch (SystemException e) {
// Problem reaching device - assume root
rootDevices.put(ior, data);
}
}
}
@Override
public void execute() {
super.execute();
// If bad status, unset the devices
if (!status.isOK()) {
provider.unsetDevices();
return;
}
process(provider.getRootDevices(), rootDevices);
process(provider.getChildDevices(), childDevices);
}
private void process(EList<ScaDevice< ? >> providerDeviceList, Map<String, DeviceData> newDevicesMap) {
// Current device map
final Map<String, ScaDevice< ? >> currentDevices = new HashMap<>();
for (final ScaDevice< ? > device : providerDeviceList) {
String deviceIor = device.getIor();
currentDevices.put(deviceIor, device);
}
// Devices to remove
final Map<String, ScaDevice< ? >> removeDevices = new HashMap<>();
removeDevices.putAll(currentDevices);
removeDevices.keySet().removeAll(newDevicesMap.keySet());
// Remove devices
if (!removeDevices.isEmpty()) {
providerDeviceList.removeAll(removeDevices.values());
}
// Remove duplicates
newDevicesMap.keySet().removeAll(currentDevices.keySet());
// Add new devices to the model
for (final DeviceData deviceData : newDevicesMap.values()) {
final ScaDevice< ? > device = createDevice(deviceData.deviceObject, deviceData.deviceType);
providerDeviceList.add(device);
}
}
/**
* Determines the type of a device, narrows it, and returns a DeviceData containing the narrowed object and the
* appropriate EMF class.
*
* @param device The device to examine
* @return
*/
protected DeviceData getDeviceData(Device device) {
if (device._is_a(ExecutableDeviceHelper.id())) {
return new DeviceData(ExecutableDeviceHelper.unchecked_narrow(device), ScaPackage.Literals.SCA_EXECUTABLE_DEVICE);
} else if (device._is_a(LoadableDeviceHelper.id())) {
return new DeviceData(LoadableDeviceHelper.unchecked_narrow(device), ScaPackage.Literals.SCA_LOADABLE_DEVICE);
}
return new DeviceData(device, ScaPackage.Literals.SCA_DEVICE);
}
/**
* Create the appropriate SCA model object for the device, and update it based on the CORBA object provided.
*
* @param deviceObject The {@link Device} object for the device
* @param deviceType The EMF class in the SCA model that corresponds to the device's type
* @return The newly created model object
*/
protected ScaDevice< ? > createDevice(org.omg.CORBA.Object deviceObject, EClass deviceType) {
ScaDevice< ? > device = (ScaDevice< ? >) ScaFactory.eINSTANCE.create(deviceType);
device.setCorbaObj(deviceObject);
return device;
}
}