package com.netifera.platform.kernel.internal.probe;
import com.netifera.platform.api.channels.IChannelConnectProgress;
import com.netifera.platform.api.channels.IChannelConnecter;
import com.netifera.platform.api.dispatcher.IMessenger;
import com.netifera.platform.api.dispatcher.MessengerException;
import com.netifera.platform.api.log.ILogger;
import com.netifera.platform.api.model.IEntity;
import com.netifera.platform.api.model.ISpace;
import com.netifera.platform.api.probe.IProbe;
import com.netifera.platform.api.tasks.ITaskClient;
import com.netifera.platform.api.tools.IToolConfiguration;
import com.netifera.platform.model.ModelUpdate;
import com.netifera.platform.model.ProbeEntity;
import com.netifera.platform.model.RequestModelUpdate;
import com.netifera.platform.model.SetModelIdPrefix;
public class ProbeClient implements IProbe {
private final ProbeManagerService probeManager;
private final ProbeEntity probeEntity;
private final ILogger logger;
private final ToolClient toolClient;
private final TaskClient taskClient;
private final ModelSyncClient modelSyncClient;
private IMessenger messenger;
private final IChannelConnectProgress connectProgress;
private IChannelConnecter channelConnecter;
private ConnectState connectState = ConnectState.DISCONNECTED;
private String connectError = "";
ProbeClient(ProbeManagerService probeManager, ProbeEntity entity, ILogger logger) {
this.probeManager = probeManager;
this.probeEntity = entity;
this.logger = logger.getManager().getLogger("Probe Client");
this.logger.enableDebug();
this.connectProgress = createConnectProgress();
taskClient = new TaskClient(this, entity.getWorkspace(), logger);
toolClient = new ToolClient(this, logger);
modelSyncClient = new ModelSyncClient(this, entity.getWorkspace(), logger);
}
private IChannelConnectProgress createConnectProgress() {
return new IChannelConnectProgress() {
public void connectCompleted(IMessenger channelMessenger) {
setConnected(channelMessenger);
}
public void connectFailed(String reason, Throwable exception) {
setConnectFailed(reason, exception);
}
public void connectUpdate(String update) {
processConnectUpdate(update);
}
};
}
public void setConnected(IMessenger channelMessenger) {
connectState = ConnectState.CONNECTED;
this.messenger = channelMessenger;
messenger.setProbe(this);
if(!isLocalProbe()) {
setModelPrefixId(messenger);
startModelUpdates(messenger);
}
notifyChange();
}
private void setModelPrefixId(IMessenger messenger) {
try {
messenger.sendMessage(new SetModelIdPrefix(getProbeId()));
logger.debug("Send prefix id to probe");
} catch (MessengerException e) {
logger.warning("Failed to set model id prefix: " + e.getMessage());
}
}
private void startModelUpdates(IMessenger messenger) {
try {
messenger.sendMessage(new RequestModelUpdate(probeEntity.getUpdateIndex()));
} catch(MessengerException e) {
logger.warning("Failed to send request model update message " + e.getMessage());
}
}
private void setConnectFailed(String reason, Throwable exception) {
connectState = ConnectState.CONNECT_FAILED;
connectError = reason;
notifyChange();
}
private void processConnectUpdate(String update) {
// XXX implement me
}
public void notifyChange() {
probeManager.fireChangeEvent();
probeEntity.update();
}
public IMessenger getMessenger() {
return messenger;
}
public ITaskClient getTaskClient() {
return taskClient;
}
public IEntity getEntity() {
return probeEntity;
}
public long getProbeId() {
return probeEntity.getProbeId();
}
public ConnectState getConnectState() {
return connectState;
}
public String getConnectError() {
return connectError;
}
void setConnectState(ConnectState newState) {
this.connectState = newState;
}
public void connect() {
if(!isDisconnected()) {
logger.warning("Connect called on probe which is not disconnected");
return;
}
channelConnecter = probeManager.createChannelConnecter(probeEntity.getChannelConfig());
if(channelConnecter == null) {
logger.warning("Failed to convert entity channel configuration into a channel connecter. Config = "
+ probeEntity.getChannelConfig());
return;
}
this.connectState = ConnectState.CONNECTING;
channelConnecter.connect(connectProgress);
notifyChange();
}
public void disconnect() {
messenger.close();
}
public boolean isLocalProbe() {
return probeEntity.isLocal();
}
public String getName() {
return probeEntity.getName();
}
public boolean isConnected() {
return connectState == ConnectState.CONNECTED;
}
public boolean isDisconnected() {
return connectState == ConnectState.DISCONNECTED || connectState == ConnectState.CONNECT_FAILED;
}
public void launchTool(final String toolClassName, String toolBundle,
final IToolConfiguration configuration, ISpace space) {
toolClient.launchTool(toolClassName, configuration, space);
}
public boolean equals(Object o) {
if(!(o instanceof ProbeClient)) {
return false;
}
return ((ProbeClient)o).getProbeId() == getProbeId();
}
public int hashCode() {
return (int) getProbeId();
}
public String toString() {
return "Probe [" + probeEntity.getName() + "]";
}
public void setDisconnected() {
connectState = ConnectState.DISCONNECTED;
this.messenger = null;
notifyChange();
}
void processModelUpdate(ModelUpdate update) {
modelSyncClient.processModelUpdate(update);
}
}