diff --git a/Seminar7/code/Server/.idea/.gitignore b/Seminar7/code/Server/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Seminar7/code/Server/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/Seminar7/code/Server/.idea/misc.xml b/Seminar7/code/Server/.idea/misc.xml new file mode 100644 index 0000000..03f397c --- /dev/null +++ b/Seminar7/code/Server/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Seminar7/code/Server/.idea/modules.xml b/Seminar7/code/Server/.idea/modules.xml new file mode 100644 index 0000000..7ec00e1 --- /dev/null +++ b/Seminar7/code/Server/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Seminar7/code/Server/.idea/vcs.xml b/Seminar7/code/Server/.idea/vcs.xml new file mode 100644 index 0000000..c2365ab --- /dev/null +++ b/Seminar7/code/Server/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Seminar7/code/Server/out/production/Server/ClientResolver.class b/Seminar7/code/Server/out/production/Server/ClientResolver.class new file mode 100644 index 0000000..c5a5a53 Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/ClientResolver.class differ diff --git a/Seminar7/code/Server/out/production/Server/Computer.class b/Seminar7/code/Server/out/production/Server/Computer.class new file mode 100644 index 0000000..31fc3ed Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/Computer.class differ diff --git a/Seminar7/code/Server/out/production/Server/ComputerBuilder.class b/Seminar7/code/Server/out/production/Server/ComputerBuilder.class new file mode 100644 index 0000000..bbb31ea Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/ComputerBuilder.class differ diff --git a/Seminar7/code/Server/out/production/Server/Main.class b/Seminar7/code/Server/out/production/Server/Main.class new file mode 100644 index 0000000..8072f8b Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/Main.class differ diff --git a/Seminar7/code/Server/out/production/Server/ServerHandler.class b/Seminar7/code/Server/out/production/Server/ServerHandler.class new file mode 100644 index 0000000..776302f Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/ServerHandler.class differ diff --git a/Seminar7/code/Server/out/production/Server/Store.class b/Seminar7/code/Server/out/production/Server/Store.class new file mode 100644 index 0000000..d80240d Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/Store.class differ diff --git a/Seminar7/code/Server/out/production/Server/StoreSeeder.class b/Seminar7/code/Server/out/production/Server/StoreSeeder.class new file mode 100644 index 0000000..4f86982 Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/StoreSeeder.class differ diff --git a/Seminar7/code/Server/out/production/Server/StreamCommunicator.class b/Seminar7/code/Server/out/production/Server/StreamCommunicator.class new file mode 100644 index 0000000..0b1e980 Binary files /dev/null and b/Seminar7/code/Server/out/production/Server/StreamCommunicator.class differ diff --git a/Seminar7/code/Server/src/ClientResolver.java b/Seminar7/code/Server/src/ClientResolver.java new file mode 100644 index 0000000..57eda9f --- /dev/null +++ b/Seminar7/code/Server/src/ClientResolver.java @@ -0,0 +1,34 @@ +import java.io.PrintStream; +import java.net.Socket; +import java.util.Scanner; + +public class ClientResolver implements Runnable { + private Socket clientSocket; + private Store store; + + public ClientResolver(Socket socket, Store store) + { + this.clientSocket = socket; + this.store = store; + } + + public void run() + { + Scanner in = null; + PrintStream out = null; + try { + in = new Scanner(clientSocket.getInputStream()); + out = new PrintStream(clientSocket.getOutputStream()); + StreamCommunicator communicator = new StreamCommunicator(in, out); + + var server = new ServerHandler(communicator, this.store); + server.startCommunication(); + } catch (Exception e) { + System.out.println(e.getMessage()); + System.out.println("Connection closed."); + } finally { + in.close(); + out.close(); + } + } +} diff --git a/Seminar7/code/Server/src/Computer.java b/Seminar7/code/Server/src/Computer.java new file mode 100644 index 0000000..c592ebc --- /dev/null +++ b/Seminar7/code/Server/src/Computer.java @@ -0,0 +1,76 @@ +import java.time.LocalDate; + +public class Computer { + private int id; + private String brand; + private String model; + private boolean isUsed; + private LocalDate manufacturedDate; + private int quantity; + + public Computer() { } + + public Computer(String brand, String model, boolean isUsed, LocalDate manufacturedDate, int quantity) { + this.setBrand(brand); + this.setModel(model); + this.setUsed(isUsed); + this.setManufacturedDate(manufacturedDate); + this.setQuantity(quantity); + } + + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + + public String getBrand() { + return brand; + } + public void setBrand(String brand) { + this.brand = brand; + } + + public String getModel() { + return model; + } + public void setModel(String model) { + this.model = model; + } + + public boolean isUsed() { + return isUsed; + } + public void setUsed(boolean used) { + isUsed = used; + } + + public LocalDate getManufacturedDate() { + return manufacturedDate; + } + public void setManufacturedDate(LocalDate manufacturedDate) { + this.manufacturedDate = manufacturedDate; + } + + public int getQuantity() { + return quantity; + } + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Computer: #").append(this.getId()).append("\t") + .append(this.getBrand()).append(" ").append(this.getModel()).append("\t") + .append("Year of manufacturing: ").append(this.getManufacturedDate().toString()).append("\t") + .append("Quantity: ").append(this.getQuantity()).append("\t"); + if(this.isUsed()) { + sb.append("Computer is used").append("\t"); + } + + return sb.toString(); + } +} diff --git a/Seminar7/code/Server/src/ComputerBuilder.java b/Seminar7/code/Server/src/ComputerBuilder.java new file mode 100644 index 0000000..2c161ad --- /dev/null +++ b/Seminar7/code/Server/src/ComputerBuilder.java @@ -0,0 +1,14 @@ +import java.time.LocalDate; + +public class ComputerBuilder { + public static Computer build(StreamCommunicator communicator) { + Computer computer = new Computer(); + computer.setBrand(communicator.communicateMessage("Enter brand:")); + computer.setModel(communicator.communicateMessage("Enter model:")); + computer.setManufacturedDate(LocalDate.parse( + communicator.communicateMessage("Enter date (in format: yyyy-mm-dd):"))); + computer.setUsed(Boolean.parseBoolean(communicator.communicateMessage("Is used:"))); + computer.setQuantity(Integer.parseInt(communicator.communicateMessage("Quantity:"))); + return computer; + } +} diff --git a/Seminar7/code/Server/src/Main.java b/Seminar7/code/Server/src/Main.java new file mode 100644 index 0000000..99c652c --- /dev/null +++ b/Seminar7/code/Server/src/Main.java @@ -0,0 +1,29 @@ +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; + +public class Main { + private static final int SOCKET_PORT = 5038; //Any random free port + + public static void main(String[] args) { + ServerSocket server = null; + Store store = StoreSeeder.getSeededStore(); + + try { + server = new ServerSocket(SOCKET_PORT); + + while (true) { + Socket client = server.accept(); + System.out.println("Connection established: " + client.getInetAddress().getHostAddress()); + + ClientResolver resolver = new ClientResolver(client, store); + new Thread(resolver).start(); + } + } catch (SocketException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/Seminar7/code/Server/src/ServerHandler.java b/Seminar7/code/Server/src/ServerHandler.java new file mode 100644 index 0000000..dee0e11 --- /dev/null +++ b/Seminar7/code/Server/src/ServerHandler.java @@ -0,0 +1,45 @@ +import java.io.PrintStream; +import java.util.Scanner; + +public class ServerHandler { + private StreamCommunicator communicator; + private Store store; + + public ServerHandler(StreamCommunicator communicator, Store store) { + this.communicator = communicator; + this.store = store; + } + + public void startCommunication() { + int choice = Integer.parseInt(communicator.communicateMessage("Write 1 for administrator and 2 for client")); + switch(choice) { + case 1: + this.communicateAdmin(); + break; + case 2: + this.communicateCustomer(); + break; + default: + communicator.communicateMessage("Not an option"); + } + } + + private void communicateAdmin() { + communicator.addMessage("Entering a new computer details."); + Computer computer = ComputerBuilder.build(communicator); + this.store.addComputer(computer); + } + + private void communicateCustomer() { + communicator.communicateMessage("Buying a computer.", + this.store.getAvailableComputers(), + "Which computer would you like to buy"); + int computerId = Integer.parseInt(communicator.communicateMessage()); + int quantity = Integer.parseInt(communicator.communicateMessage("How many?")); + try { + store.sellComputers(computerId, quantity); + } catch (Exception ex) { + communicator.communicateMessage(ex.getMessage()); + } + } +} diff --git a/Seminar7/code/Server/src/Store.java b/Seminar7/code/Server/src/Store.java new file mode 100644 index 0000000..c04f25d --- /dev/null +++ b/Seminar7/code/Server/src/Store.java @@ -0,0 +1,43 @@ +import java.util.*; + +public class Store { + private List availableComputers = Collections.synchronizedList(new ArrayList<>()); + + public void addComputer(Computer computer) { + computer.setId(this.availableComputers.size()); + this.availableComputers.add(computer); + } + + public String getAvailableComputers() { + StringBuffer sb = new StringBuffer(); + for (var computer : this.availableComputers) { + sb.append(computer); + } + + return sb.toString(); + } + + public void sellComputers(int computerId, int desiredQuantity) { + synchronized (this.availableComputers) { + var computerInStock = this.availableComputers.stream() + .filter(c -> c.getId() == computerId).findFirst(); + + if (computerInStock.isEmpty()) { + throw new IllegalArgumentException("Computer with id " + computerId + " doesn't exist."); + } + + Computer computer = computerInStock.get(); + int newQuantity = computer.getQuantity() - desiredQuantity; + if (newQuantity < 0) { + throw new IllegalArgumentException("There are only " + computer.getQuantity() + " computers left." + + " We cannot sell you " + desiredQuantity); + } + + if(newQuantity == 0) { + this.availableComputers.remove(computer); + } else { + computer.setQuantity(newQuantity); + } + } + } +} diff --git a/Seminar7/code/Server/src/StoreSeeder.java b/Seminar7/code/Server/src/StoreSeeder.java new file mode 100644 index 0000000..dc8f300 --- /dev/null +++ b/Seminar7/code/Server/src/StoreSeeder.java @@ -0,0 +1,17 @@ +import java.time.LocalDate; + +public class StoreSeeder { + public static Store getSeededStore() { + Store store = new Store(); + populate(store); + return store; + } + + private static void populate(Store store) { + store.addComputer(new Computer("Lenovo", "T15", false, LocalDate.now(), 5)); + store.addComputer(new Computer("Asus", "Zenbook", + true, LocalDate.of(2020, 10, 1), 2)); + store.addComputer(new Computer("Apple", "Macbook Pro", + false, LocalDate.of(2021, 10, 31), 30)); + } +} diff --git a/Seminar7/code/Server/src/StreamCommunicator.java b/Seminar7/code/Server/src/StreamCommunicator.java new file mode 100644 index 0000000..c773bba --- /dev/null +++ b/Seminar7/code/Server/src/StreamCommunicator.java @@ -0,0 +1,32 @@ +import java.io.PrintStream; +import java.lang.invoke.StringConcatException; +import java.util.*; + +public class StreamCommunicator { + private Scanner in; + private PrintStream out; + private List messages; + + public StreamCommunicator(Scanner in, PrintStream out) { + this.in = in; + this.out = out; + this.messages = new ArrayList<>(); + } + + public void addMessage(String message) { + this.messages.add(message); + } + + public String communicateMessage() { + var result = this.communicateMessage(this.messages.toArray(String[]::new)); + this.messages.clear(); + return result; + } + + public String communicateMessage(String ...messsages) { + String messageToSend = Arrays.stream(messsages).reduce("", + (String total, String current) -> total + current); + out.println(messageToSend); + return in.nextLine(); + } +} diff --git a/Seminar7/notes/Seminar0701.png b/Seminar7/notes/Seminar0701.png new file mode 100644 index 0000000..7eb3b85 Binary files /dev/null and b/Seminar7/notes/Seminar0701.png differ diff --git a/Seminar7/notes/Seminar0702.png b/Seminar7/notes/Seminar0702.png new file mode 100644 index 0000000..c301ff3 Binary files /dev/null and b/Seminar7/notes/Seminar0702.png differ diff --git a/Seminar7/notes/Seminar0703.png b/Seminar7/notes/Seminar0703.png new file mode 100644 index 0000000..2d00f0c Binary files /dev/null and b/Seminar7/notes/Seminar0703.png differ