package Connection.socket; import java.net.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import classes.HolonElement; import classes.HolonObject; import ui.controller.Control; import java.io.*; public class Server implements Runnable{ private ServerSocket serverSocket; private Socket clientSocket; private DataOutputStream out; private DataInputStream in; private boolean stopped = false; private boolean connection = false; private ui.view.component.Console console; private HolonObject observed; private HolonObjectModel modelField; private HolonObjectModel newModelField; private Control control; public Server(int port, ui.view.component.Console console, HolonObject observed, Control control) throws IOException { this.observed = observed; this.console = console; this.control = control; //Bind Port serverSocket = new ServerSocket(port); //Wait for Connection Thread serverThread = new Thread(this); serverThread.start(); this.modelField = createModel(); this.newModelField = createModel(); } public void stopServer() throws IOException { stopped = true; stopConnection(); if(serverSocket != null)serverSocket.close(); console.println("Server Closed"); } private void stopConnection() throws IOException { connection = false; if(in != null)in.close(); if(out != null)out.close(); if(clientSocket != null)clientSocket.close(); } @Override public void run() { while(!stopped) { try { //Wait for new Connection console.println("Wait for Connection.."); clientSocket = serverSocket.accept(); console.println("Connection from " + clientSocket.getInetAddress() + ":" + clientSocket.getPort()); connection = true; out = new DataOutputStream(clientSocket.getOutputStream()); in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream())); if(observed == null) stopConnection(); this.modelField = createModel(); Thread updateThread = new Thread(new UpdateLoop()); updateThread.start(); //InputLoop try { inputLoop(); }catch(EOFException e){ console.println("Connection Closed"); } stopConnection(); } catch(SocketException e){ //ServerSocket is closed stopped = true; } catch (IOException e) { e.printStackTrace(); } connection = false; } } private void inputLoop() throws IOException { while (connection) { //WaitForInput byte inputByte = in.readByte(); //UpdateHoleg if (inputByte == Command.SetAmount) { if(observed == null) stopConnection(); console.println("Res: [" + inputByte + "] -> SetAmount"); int index = in.readInt(); int amount = in.readInt(); modelField.getElements().get(index).amount = amount; observed.getElements().get(index).setAmount(amount); }else if (inputByte == Command.SetEnable) { if(observed == null) stopConnection(); console.println("Res: [" + inputByte + "] -> SetEnable"); int index = in.readInt(); boolean enabled = in.readBoolean(); modelField.getElements().get(index).enabled = enabled; observed.getElements().get(index).setActive(enabled); }else if (inputByte == Command.IncreaseAmount) { if(observed == null) stopConnection(); console.println("Res: [" + inputByte + "] -> IncreaseAmount"); int index = in.readInt(); modelField.getElements().get(index).amount++; HolonElement ele = observed.getElements().get(index); ele.setAmount(ele.getAmount()+1); }else if (inputByte == Command.DecreaseAmount) { if(observed == null) stopConnection(); console.println("Res: [" + inputByte + "] -> DecreaseAmount"); int index = in.readInt(); modelField.getElements().get(index).amount--; HolonElement ele = observed.getElements().get(index); ele.setAmount(ele.getAmount()-1); } else{ console.println("Res: [" + inputByte + "] -> unknown"); } control.calculateStateAndVisualForCurrentTimeStep(); control.updateCanvas(); control.getGui().triggerUpdateController(null); } } private HolonObjectModel createModel() { HolonObjectModel model = new HolonObjectModel(); int index = 0; for(HolonElement ele :observed.getElements()) { model.add(ele, index++); } return model; } public class UpdateLoop implements Runnable{ public UpdateLoop(){ } @Override public void run() { sendUpdate(); while(!stopped && connection) { if(checkForUpdates()){ sendUpdate(); }else { waitOneSecond(); } } } private void waitOneSecond() { //wait one second try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { } } private boolean checkForUpdates() { //TODO Delete And CheckforUpdatesReal newModelField = createModel(); if(compareModels(modelField,newModelField)) { return false; } modelField = newModelField; return true; } /** * Returns true if both are the same. * @param modelField * @param newModelField * @return */ private void sendUpdate() { try { if(observed == null) stopConnection(); console.println("Send: [" + Command.Update + "] -> Update"); out.writeByte(Command.Update); out.writeInt(modelField.size()); for(HolonElementWrapper wrapper : modelField.getElements()) { out.writeUTF(wrapper.name); out.writeInt(wrapper.amount); out.writeFloat(wrapper.energy); out.writeBoolean(wrapper.enabled); } } catch (IOException e) { if(connection)console.println(e.getMessage()); } } } private boolean compareModels(HolonObjectModel model, HolonObjectModel newModel) { if(model.size() != newModel.size()) { return false; } for(int i = 0; i < model.size(); i++) { if(!model.getElements().get(i).equals(newModel.getElements().get(i))) { return false; } } return true; } public void setObserved(HolonObject observed) { this.observed = observed; } public class Command { //InputCommands public static final int SetAmount = 10; public static final int SetEnable = 11; public static final int IncreaseAmount = 12; public static final int DecreaseAmount = 13; //UpdateResiveCommands public static final int Update = 20; } public class HolonObjectModel { //Field private List elements; private String holonObjectName; //constructor public HolonObjectModel(){ elements = new ArrayList(); } public void add(HolonElement ele, int index ) { String name = ele.getEleName(); int amount =ele.getAmount(); float energy = ele.getEnergyPerElement(); boolean enabled = ele.isActive(); elements.add(new HolonElementWrapper(name, amount, energy, enabled, index)); } public int size() { return elements.size(); } //Getter/Setter public List getElements() { return elements; } public String getHolonObjectName() { return holonObjectName; } public void setHolonObjectName(String holonObjectName) { this.holonObjectName = holonObjectName; } } public class HolonElementWrapper{ public int index; public String name; public int amount; public float energy; public boolean enabled; public HolonElementWrapper(){ } public HolonElementWrapper(String name, int amount, float energy, boolean enabled, int index){ this.name = name; this.amount = amount; this.energy = energy; this.enabled = enabled; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof HolonElementWrapper)) { return false; } HolonElementWrapper element = (HolonElementWrapper) obj; return this.name.compareTo(element.name) == 0 && this.amount == element.amount && this.energy == element.energy && this.enabled == element.enabled; } } }