package eu.hgross.blaubot.core;
import eu.hgross.blaubot.core.acceptor.IBlaubotConnectionListener;
import eu.hgross.blaubot.messaging.BlaubotChannelManager;
import eu.hgross.blaubot.util.KingdomCensusLifecycleListener;
/**
* The root object for all BlaubotKingdoms connected to the BlaubotServer.
* It holds the ChannelManager and all connections to this kingdom in a ConnectionManager.
*/
public class BlaubotKingdom {
private static final String LOG_TAG = "BlaubotKingdom";
/**
* The king device. It is used to address this kindom by the king's uniqueDeviceId.
*/
private final IBlaubotDevice kingDevice;
/**
* Dispatches the onDeviceLeft/onJoin events to lifecycle listeners.
*/
private final LifeCycleEventDispatcher lifeCycleEventDispatcher;
/**
* our own device
*/
private final IBlaubotDevice ownDevice;
/**
* The always client mode ChannelManager responsible for the kingdom
*/
private BlaubotChannelManager channelManager;
/**
* The managed connection.
* May be null, if manageConnection was never called.
*/
private IBlaubotConnection managedConnection;
/**
* Listens to lifecycle events to have the kingdom's state at hand.
*/
private KingdomCensusLifecycleListener kingdomCensusLifecycleListener;
/**
* @param ownDevice the own device
* @param kingDevice the device object for the kingdom's king device
*/
public BlaubotKingdom(IBlaubotDevice ownDevice, IBlaubotDevice kingDevice) {
this.ownDevice = ownDevice;
this.kingDevice = kingDevice;
// create components
this.channelManager = new BlaubotChannelManager(ownDevice.getUniqueDeviceID());
this.lifeCycleEventDispatcher = new LifeCycleEventDispatcher(ownDevice);
this.kingdomCensusLifecycleListener = new KingdomCensusLifecycleListener(ownDevice);
// wire components
this.channelManager.addAdminMessageListener(lifeCycleEventDispatcher);
// // debug listener
// this.channelManager.addAdminMessageListener(new IBlaubotAdminMessageListener() {
// @Override
// public void onAdminMessage(AbstractAdminMessage adminMessage) {
// System.out.println("Kingdom of " + BlaubotKingdom.this.kingDevice.getUniqueDeviceID() + " Got admin message: " + adminMessage);
// }
// });
this.lifeCycleEventDispatcher.addLifecycleListener(this.kingdomCensusLifecycleListener);
}
/**
* Choses the connection to the kingDevice and starts the kingdom management.
*
* @param connection the king-connection that is to be managed by this kingdom instance
* @throws IllegalStateException if manageConncetion was called before
*/
protected void manageConnection(BlaubotKingdomConnection connection) {
if (this.managedConnection != null) {
throw new IllegalStateException("There was already a connection.");
}
this.channelManager.setMaster(false);
this.channelManager.activate();
// if the connection dies, we stop the channel manager
connection.addConnectionListener(new IBlaubotConnectionListener() {
@Override
public void onConnectionClosed(IBlaubotConnection connection) {
// onConncected/onDisconnected has to be triggered by the LifeCycleEventDispatcher on disconnect of the managed connection
if (managedConnection != null) {
final String kingUniqueDeviceID = getKingDevice().getUniqueDeviceID();
lifeCycleEventDispatcher.notifyDisconnectedFromNetwork(kingUniqueDeviceID);
}
disconnectKingdom();
}
});
this.managedConnection = connection;
this.channelManager.addConnection(connection);
this.lifeCycleEventDispatcher.notifyConnectedToNetwork();
}
/**
* Adds a listener that gets invoked, if this kingdom disconnected
*
* @param disconnectListener the listener
*/
public void addDisconnectListener(IBlaubotConnectionListener disconnectListener) {
if (this.managedConnection != null) {
this.managedConnection.addConnectionListener(disconnectListener);
}
}
/**
* Closes all connections and releases resources regarding this kingdom.
*/
public void disconnectKingdom() {
if (this.managedConnection != null) {
this.managedConnection.disconnect();
}
this.channelManager.reset();
this.channelManager.deactivate();
}
/**
* Adds a listener to this kingdom's life cycle events
*
* @param lifecycleListener the listener to be added
*/
public void addLifecycleListener(ILifecycleListener lifecycleListener) {
lifeCycleEventDispatcher.addLifecycleListener(lifecycleListener);
}
/**
* Removes a listener to this kingdom's life cycle events
*
* @param lifecycleListener the listener to be removed
*/
public void removeLifecycleListener(ILifecycleListener lifecycleListener) {
lifeCycleEventDispatcher.removeLifecycleListener(lifecycleListener);
}
/**
* The channel manage to manage channels.
*
* @return channel manager
*/
public BlaubotChannelManager getChannelManager() {
return channelManager;
}
/**
* Returns the king device, which is the discriminator for a kingdom.
*
* @return king device
*/
public IBlaubotDevice getKingDevice() {
return kingDevice;
}
/**
* our own device
*
* @return device
*/
public IBlaubotDevice getOwnDevice() {
return ownDevice;
}
/**
* A KingdomCensusLifecycleListener keeping track of the connected devices.
* You can poll the devices, current prince, ... from here.
* @return the census listener
*/
public KingdomCensusLifecycleListener getKingdomCensusLifecycleListener() {
return kingdomCensusLifecycleListener;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BlaubotKingdom that = (BlaubotKingdom) o;
if (!kingDevice.equals(that.kingDevice)) return false;
if (managedConnection != null ? !managedConnection.equals(that.managedConnection) : that.managedConnection != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = kingDevice.hashCode();
result = 31 * result + (managedConnection != null ? managedConnection.hashCode() : 0);
return result;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("BlaubotKingdom{");
sb.append("kingDevice=").append(kingDevice);
sb.append(", managedConnection=").append(managedConnection);
sb.append('}');
return sb.toString();
}
}