diff --git a/client/src/main/java/ch/zhaw/pm2/multichat/client/ChatWindowController.java b/client/src/main/java/ch/zhaw/pm2/multichat/client/ChatWindowController.java index b780b49..a5ddbaa 100644 --- a/client/src/main/java/ch/zhaw/pm2/multichat/client/ChatWindowController.java +++ b/client/src/main/java/ch/zhaw/pm2/multichat/client/ChatWindowController.java @@ -17,21 +17,31 @@ import java.io.IOException; import static ch.zhaw.pm2.multichat.protocol.ConnectionHandler.State.*; + public class ChatWindowController { private ClientConnectionHandler connectionHandler; private ClientMessageList messages; private final WindowCloseHandler windowCloseHandler = new WindowCloseHandler(); - @FXML private Pane rootPane; - @FXML private TextField serverAddressField; - @FXML private TextField serverPortField; - @FXML private TextField userNameField; - @FXML private TextField messageField; - @FXML private TextArea messageArea; - @FXML private Button connectButton; - @FXML private Button sendButton; - @FXML private TextField filterValue; + @FXML + private Pane rootPane; + @FXML + private TextField serverAddressField; + @FXML + private TextField serverPortField; + @FXML + private TextField userNameField; + @FXML + private TextField messageField; + @FXML + private TextArea messageArea; + @FXML + private Button connectButton; + @FXML + private Button sendButton; + @FXML + private TextField filterValue; public void setMessages(ClientMessageList messages) { @@ -39,7 +49,7 @@ public class ChatWindowController { messageListener(); } - public void setConnectionHandler(ClientConnectionHandler connectionHandler){ + public void setConnectionHandler(ClientConnectionHandler connectionHandler) { this.connectionHandler = connectionHandler; startConnectionHandlerListener(); serverAddressField.setText(connectionHandler.getServerAddressProperty().get()); @@ -51,7 +61,7 @@ public class ChatWindowController { } @FXML - private void toggleConnection () { + private void toggleConnection() { if (connectionHandler == null || connectionHandler.getStateProperty().get() != CONNECTED) { connect(); } else { @@ -59,16 +69,20 @@ public class ChatWindowController { } } + private void connect() { try { messages.clear(); // clear message list startConnectionHandler(); connectionHandler.connect(); - } catch(ChatProtocolException | IOException e) { + } catch (ChatProtocolException | IOException e) { addError(e.getMessage()); } } + /** + * Initiates disconnecting of the connectionHandler, also checks if connectionHandler is avaible. + */ private void disconnect() { if (connectionHandler == null) { addError("No connection handler"); @@ -81,6 +95,9 @@ public class ChatWindowController { } } + /** + * + */ @FXML private void message() { String messageString = messageField.getText().strip(); @@ -98,13 +115,13 @@ public class ChatWindowController { } @FXML - private void applyFilter( ) { + private void applyFilter() { Platform.runLater(() -> this.messageArea.setText(messages.getFilteredMessages(filterValue.getText().strip()))); } private void startConnectionHandler() throws IOException { String userName = userNameField.getText(); - if(!userName.contains(" ")) { + if (!userName.contains(" ")) { String serverAddress = serverAddressField.getText(); int serverPort = Integer.parseInt(serverPortField.getText()); connectionHandler.initialize(serverAddress, serverPort, userName); @@ -128,7 +145,7 @@ public class ChatWindowController { connectButton.setText((newState == CONNECTED || newState == CONFIRM_DISCONNECT) ? "Disconnect" : "Connect"); } }); - if(newState == DISCONNECTED){ + if (newState == DISCONNECTED) { connectionHandler.stopReceiving(); } } @@ -200,6 +217,7 @@ public class ChatWindowController { }); } + private void messageListener() { messages.getChangedProperty().addListener(new ChangeListener() { @Override diff --git a/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientConnectionHandler.java b/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientConnectionHandler.java index f67ceb0..da5c1a9 100644 --- a/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientConnectionHandler.java +++ b/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientConnectionHandler.java @@ -13,19 +13,20 @@ import java.net.SocketException; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; + import static ch.zhaw.pm2.multichat.protocol.ConnectionHandler.State.*; public class ClientConnectionHandler extends ConnectionHandler implements Runnable { - private final Pattern messagePattern = Pattern.compile( "^(?:@(\\S*))?\\s*(.*)$" ); + private final Pattern messagePattern = Pattern.compile("^(?:@(\\S*))?\\s*(.*)$"); private SimpleStringProperty userName; - private SimpleObjectProperty state; - private ClientMessageList messages; - private SimpleStringProperty serverAddress; - private SimpleIntegerProperty serverPort; + private final SimpleObjectProperty state; + private final ClientMessageList messages; + private final SimpleStringProperty serverAddress; + private final SimpleIntegerProperty serverPort; - public ClientConnectionHandler(ClientMessageList messages) { + public ClientConnectionHandler(ClientMessageList messages) { super(); this.messages = messages; state = new SimpleObjectProperty<>(State.NEW); @@ -39,24 +40,30 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab this.serverAddress.set(serverAddress); this.serverPort.set(serverPort); setConnection(NetworkHandler.openConnection(serverAddress, serverPort)); - this.userName = new SimpleStringProperty((userName == null || userName.isBlank())? USER_NONE : userName); + this.userName = new SimpleStringProperty((userName == null || userName.isBlank()) ? USER_NONE : userName); } - public SimpleStringProperty getServerAddressProperty() { return serverAddress; } + public SimpleStringProperty getServerAddressProperty() { + return serverAddress; + } - public SimpleIntegerProperty getServerPortProperty() { return serverPort; } + public SimpleIntegerProperty getServerPortProperty() { + return serverPort; + } public SimpleObjectProperty getStateProperty() { return this.state; } - public SimpleStringProperty getUserNameProperty() { return userName; } + public SimpleStringProperty getUserNameProperty() { + return userName; + } - public void setState (State newState) { + public void setState(State newState) { state.set(newState); } - public void run () { + public void run() { startReceiving(); } @@ -77,9 +84,9 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab System.out.println("Connection terminated by remote"); this.setState(DISCONNECTED); System.err.println("Unregistered because connection terminated" + e.getMessage()); - } catch(IOException e) { + } catch (IOException e) { System.err.println("Communication error" + e); - } catch(ClassNotFoundException e) { + } catch (ClassNotFoundException e) { System.err.println("Received object of unknown type" + e.getMessage()); } System.out.println("Stopped Connection Handler"); @@ -131,11 +138,11 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab this.userName.set(reciever); this.serverPort.set(getConnection().getRemotePort()); this.serverAddress.set(getConnection().getRemoteHost()); - messages.addMessage(new Message(Message.MessageType.INFO,sender,reciever,payload)); + messages.addMessage(new Message(Message.MessageType.INFO, sender, reciever, payload)); System.out.println("CONFIRM: " + payload); this.setState(CONNECTED); } else if (state.get() == CONFIRM_DISCONNECT) { - messages.addMessage(new Message(Message.MessageType.INFO,sender,reciever,payload)); + messages.addMessage(new Message(Message.MessageType.INFO, sender, reciever, payload)); System.out.println("CONFIRM: " + payload); this.setState(DISCONNECTED); } else { @@ -146,7 +153,7 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab System.out.println("DISCONNECT: Already in disconnected: " + payload); return; } - messages.addMessage(new Message(Message.MessageType.INFO,sender,reciever,payload)); + messages.addMessage(new Message(Message.MessageType.INFO, sender, reciever, payload)); System.out.println("DISCONNECT: " + payload); this.setState(DISCONNECTED); } else if (type.equals(getDataTypeMessage())) { @@ -154,10 +161,10 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab System.out.println("MESSAGE: Illegal state " + state + " for message: " + payload); return; } - messages.addMessage(new Message(Message.MessageType.MESSAGE,sender,reciever,payload)); - System.out.println("MESSAGE: From " + sender + " to " + reciever + ": "+ payload); + messages.addMessage(new Message(Message.MessageType.MESSAGE, sender, reciever, payload)); + System.out.println("MESSAGE: From " + sender + " to " + reciever + ": " + payload); } else if (type.equals(getDataTypeError())) { - messages.addMessage(new Message(Message.MessageType.ERROR,sender,reciever,payload)); + messages.addMessage(new Message(Message.MessageType.ERROR, sender, reciever, payload)); System.out.println("ERROR: " + payload); } else { System.out.println("Unknown data type received: " + type); @@ -172,18 +179,18 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab if (getConnection().isAvailable()) { new StringBuilder(); String data = new StringBuilder() - .append(sender+"\n") - .append(receiver+"\n") - .append(type+"\n") - .append(payload+"\n") - .toString(); + .append(sender + "\n") + .append(receiver + "\n") + .append(type + "\n") + .append(payload + "\n") + .toString(); try { getConnection().send(data); } catch (SocketException e) { System.err.println("Connection closed: " + e.getMessage()); } catch (EOFException e) { System.out.println("Connection terminated by remote"); - } catch(IOException e) { + } catch (IOException e) { System.err.println("Communication error: " + e.getMessage()); } } @@ -191,13 +198,14 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab public void connect() throws ChatProtocolException { if (state.get() != NEW) throw new ChatProtocolException("Illegal state for connect: " + state); - this.sendData(userName.get(), USER_NONE, getDataTypeConnect(),null); + this.sendData(userName.get(), USER_NONE, getDataTypeConnect(), null); this.setState(CONFIRM_CONNECT); } public void disconnect() throws ChatProtocolException { - if (state.get() != NEW && state.get() != CONNECTED) throw new ChatProtocolException("Illegal state for disconnect: " + state); - this.sendData(userName.get(), USER_NONE, getDataTypeDisconnect(),null); + if (state.get() != NEW && state.get() != CONNECTED) + throw new ChatProtocolException("Illegal state for disconnect: " + state); + this.sendData(userName.get(), USER_NONE, getDataTypeDisconnect(), null); this.setState(CONFIRM_DISCONNECT); } @@ -208,11 +216,11 @@ public class ClientConnectionHandler extends ConnectionHandler implements Runnab if (matcher.find()) { String receiver = matcher.group(1); String message = matcher.group(2); - if(message.length() < 1){ + if (message.length() < 1) { return false; } if (receiver == null || receiver.isBlank()) receiver = ClientConnectionHandler.USER_ALL; - this.sendData(userName.get(), receiver, getDataTypeMessage(),message); + this.sendData(userName.get(), receiver, getDataTypeMessage(), message); return true; } else { return false; diff --git a/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientMessageList.java b/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientMessageList.java index 7105c5b..5f3f48f 100644 --- a/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientMessageList.java +++ b/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientMessageList.java @@ -7,35 +7,38 @@ import java.util.List; public class ClientMessageList { private List messages = new ArrayList<>(); - private SimpleBooleanProperty changed = new SimpleBooleanProperty(false); + private final SimpleBooleanProperty changed = new SimpleBooleanProperty(false); public void addMessage(Message message) { - messages.add(message); - changed.set(!changed.get()); + messages.add(message); + changed.set(!changed.get()); } - public String getFilteredMessages(String filter) { + public String getFilteredMessages(String filter) { StringBuilder result = new StringBuilder(); - boolean showAll = filter == null || filter.isBlank(); - for(Message message : messages) { - if(showAll || message.matchesFilter(filter)) - { + boolean showAll = filter == null || filter.isBlank(); + for (Message message : messages) { + if (showAll || message.matchesFilter(filter)) { switch (message.getType()) { - case MESSAGE -> result.append(String.format("[%s -> %s] %s\n", message.getSender(), message.getReceiver(), message.getText())); + case MESSAGE -> + result.append(String.format("[%s -> %s] %s\n", message.getSender(), message.getReceiver(), message.getText())); case ERROR -> result.append(String.format("[ERROR] %s\n", message.getText())); case INFO -> result.append(String.format("[INFO] %s\n", message.getText())); - default -> result.append(String.format("[ERROR] %s\n", "Unexpected message type: " + message.getType())); + default -> + result.append(String.format("[ERROR] %s\n", "Unexpected message type: " + message.getType())); } - } - } + } + } return result.toString(); - } + } public void clear() { messages = new ArrayList<>(); changed.set(!changed.get()); } - public SimpleBooleanProperty getChangedProperty() { return changed; } + public SimpleBooleanProperty getChangedProperty() { + return changed; + } } diff --git a/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientUI.java b/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientUI.java index 67a1d96..5fbdbf5 100644 --- a/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientUI.java +++ b/client/src/main/java/ch/zhaw/pm2/multichat/client/ClientUI.java @@ -7,8 +7,8 @@ import javafx.scene.layout.Pane; import javafx.stage.Stage; public class ClientUI extends Application { - private ClientMessageList clientMessageList = new ClientMessageList(); - private ClientConnectionHandler connectionHandler = new ClientConnectionHandler(clientMessageList); + private final ClientMessageList clientMessageList = new ClientMessageList(); + private final ClientConnectionHandler connectionHandler = new ClientConnectionHandler(clientMessageList); @Override public void start(Stage primaryStage) { @@ -34,7 +34,7 @@ public class ClientUI extends Application { primaryStage.setTitle("Multichat Client"); primaryStage.show(); primaryStage.setMinWidth(primaryStage.getWidth()); //use automatically computed size as Minimum Size. - } catch(Exception e) { + } catch (Exception e) { System.err.println("Error starting up UI" + e.getMessage()); } } diff --git a/client/src/main/java/ch/zhaw/pm2/multichat/client/Message.java b/client/src/main/java/ch/zhaw/pm2/multichat/client/Message.java index d805f68..f30a445 100644 --- a/client/src/main/java/ch/zhaw/pm2/multichat/client/Message.java +++ b/client/src/main/java/ch/zhaw/pm2/multichat/client/Message.java @@ -1,20 +1,21 @@ package ch.zhaw.pm2.multichat.client; /** -A Message object represents one Message of a client. Can be stored in ClientMessageList. + * A Message object represents one Message of a client. Can be stored in ClientMessageList. */ public class Message { - private MessageType type; - private String sender; - private String receiver; - private String text; + private final MessageType type; + private final String sender; + private final String receiver; + private final String text; /** * Constructor of Message. Needs all Information about a Message to save them. - * @param type Message (if it's a message typed by a user), Error or Information (if it is generated automatically, in this case sender and reciever will be null) - * @param sender The User who has sent the message. + * + * @param type Message (if it's a message typed by a user), Error or Information (if it is generated automatically, in this case sender and reciever will be null) + * @param sender The User who has sent the message. * @param receiver The User who should recieve the message. - * @param text The Text of the message. + * @param text The Text of the message. */ public Message(MessageType type, String sender, String receiver, String text) { this.type = type; @@ -25,13 +26,14 @@ public class Message { /** * Checks if the Filter String is contained in one of the datafields sender, receiver or text + * * @param filter The Filter String * @return true if it the Filter String is contained in a datafield. */ - public boolean matchesFilter(String filter){ + public boolean matchesFilter(String filter) { return (sender != null && sender.contains(filter)) || - (receiver != null && receiver.contains(filter)) || - (text != null && text.contains(filter)); + (receiver != null && receiver.contains(filter)) || + (text != null && text.contains(filter)); } /** @@ -63,7 +65,7 @@ public class Message { } /** - * Enummeration of Message Types. + * Enumeration of Message Types. */ public enum MessageType { INFO, MESSAGE, ERROR; diff --git a/server/src/main/java/ch/zhaw/pm2/multichat/server/Server.java b/server/src/main/java/ch/zhaw/pm2/multichat/server/Server.java index 7c447d6..01d9e32 100644 --- a/server/src/main/java/ch/zhaw/pm2/multichat/server/Server.java +++ b/server/src/main/java/ch/zhaw/pm2/multichat/server/Server.java @@ -19,6 +19,10 @@ public class Server { // Connection registry private Map connections = new HashMap<>(); + /** + * + * @param args + */ public static void main(String[] args) { // Parse arguments for server port. try {