package kernel; import java.io.IOException; import java.util.concurrent.CountDownLatch; import rescuecore2.Constants; import rescuecore2.config.Config; import rescuecore2.connection.Connection; import rescuecore2.connection.ConnectionException; import rescuecore2.connection.TCPConnection; import rescuecore2.connection.ConnectionListener; import rescuecore2.worldmodel.Entity; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.WorldModel; import rescuecore2.worldmodel.DefaultWorldModel; import rescuecore2.messages.Message; import rescuecore2.messages.control.GKConnectOK; import rescuecore2.messages.control.GKConnectError; import rescuecore2.messages.control.KGConnect; import rescuecore2.messages.control.KGAcknowledge; import rescuecore2.log.Logger; /** A WorldModelCreator that talks to a remote GIS. */ public class RemoteGISWorldModelCreator implements WorldModelCreator { private int nextID; @Override public WorldModel<? extends Entity> buildWorldModel(Config config) throws KernelException { Logger.info("Connecting to remote GIS..."); DefaultWorldModel<Entity> world = DefaultWorldModel.create(); CountDownLatch latch = new CountDownLatch(1); int gisPort = config.getIntValue(Constants.GIS_PORT_NUMBER_KEY, Constants.DEFAULT_GIS_PORT_NUMBER); Connection conn; try { conn = new TCPConnection(gisPort); conn.addConnectionListener(new GISConnectionListener(latch, world)); conn.startup(); conn.sendMessage(new KGConnect(1)); } catch (IOException e) { throw new KernelException("Couldn't connect to GIS", e); } catch (ConnectionException e) { throw new KernelException("Couldn't connect to GIS", e); } // Wait for a reply try { latch.await(); } catch (InterruptedException e) { throw new KernelException("Interrupted while connecting to GIS", e); } conn.shutdown(); return world; } @Override public String toString() { return "Remote GIS"; } @Override public EntityID generateID() { synchronized (this) { return new EntityID(nextID++); } } /** Listener for the GIS connection. */ private class GISConnectionListener implements ConnectionListener { private CountDownLatch latch; private DefaultWorldModel<Entity> model; public GISConnectionListener(CountDownLatch latch, DefaultWorldModel<Entity> model) { this.latch = latch; this.model = model; } public void messageReceived(Connection c, Message m) { if (m instanceof GKConnectOK) { try { // Update the internal world model model.removeAllEntities(); model.addEntities(((GKConnectOK)m).getEntities()); // Send an acknowledgement c.sendMessage(new KGAcknowledge()); Logger.info("GIS connected OK"); // Trigger the countdown latch latch.countDown(); nextID = 0; for (Entity next : model) { nextID = Math.max(nextID, next.getID().getValue()); } ++nextID; } catch (ConnectionException e) { Logger.error("RemoteGISWorldModelCreator.messageReceived", e); } } if (m instanceof GKConnectError) { Logger.error("Error connecting to remote GIS: " + ((GKConnectError)m).getReason()); latch.countDown(); } } } }