import java.io.*; import java.net.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Objects; /** * Purdue CS180 - Summer 22 - Project 5 - MessagingServer *

* This class stores the server-side part of our application. * It is in charge of processing user input and returning * data to the client. The server can handle multiple clients * at a time. * * @author Jun Shern Lim, Ivan Yang, Shaofeng Yuan * @version 31st July 2022 */ public class MessagingServer implements Runnable { public static final Object USER_DETAILS_GATEKEEPER = new Object(); public static final Object STORES_GATEKEEPER = new Object(); public static final Object NEW_MSG_GATEKEEPER = new Object(); public static final Object BLOCK_GATEKEEPER = new Object(); public static final Object INVISIBLE_GATEKEEPER = new Object(); public static final ArrayList CUSTOMER_GATEKEEPERS = new ArrayList<>(); //use this for gatekeeping private Socket socket; //each instance of the server will have its own socket to connect to its client private static ArrayList usedCustomerIDs = new ArrayList<>(); //array list of used customerIDs private static ArrayList usedSellerIDs = new ArrayList<>(); //array list of used sellerIDs private Seller seller = null; //each instance of a server will have its own seller/customer private Customer customer = null; //each instance of a server will have its own seller/customer //important to initialize the socket!! public MessagingServer(Socket socket) { this.socket = socket; } //initializes an array list of customer objects as gatekeepers public static void initializeCustomerGatekeepers() throws IOException { synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { String[] lineSplit = line.split(","); if (lineSplit[3].equals("customer")) { CUSTOMER_GATEKEEPERS.add(new Customer(lineSplit[0], lineSplit[1], lineSplit[2], lineSplit[3])); } line = br.readLine(); } } catch (FileNotFoundException e) { //do nothing } } } //returns a pointer to the customer object used to sync public static Customer getCustomerGatekeeper(int id) { for (Customer customer : CUSTOMER_GATEKEEPERS) { if (customer.getID() == id) { return customer; } } return null; } public static ArrayList getUsedCustomerIDs() { return usedCustomerIDs; } public static void addToUsedCustomerIDs(int id) { usedCustomerIDs.add(id); } public static ArrayList getUsedSellerIDs() { return usedSellerIDs; } public static void addToUsedSellerIDs(int id) { usedSellerIDs.add(id); } public static void readUsedIDs() throws IOException { synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { String[] lineSplit = line.split(","); if (lineSplit[3].equals("seller")) { if (!usedSellerIDs.contains( Character.getNumericValue(lineSplit[4].charAt(lineSplit[4].length() - 1)))) { addToUsedSellerIDs( Character.getNumericValue(lineSplit[4].charAt(lineSplit[4].length() - 1))); } } else { if (!usedCustomerIDs.contains( Character.getNumericValue(lineSplit[4].charAt(lineSplit[4].length() - 1)))) { addToUsedCustomerIDs( Character.getNumericValue(lineSplit[4].charAt(lineSplit[4].length() - 1))); } } line = br.readLine(); } } catch (FileNotFoundException e) { //don't need to do anything, means no users have been created yet } } } public static String getCurrentDateTime() { LocalDateTime curDateTime = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-ddTHH:mm:ss"); return curDateTime.format(formatter); } public static void main(String[] args) { //first create a server socket ServerSocket serverSocket; try { serverSocket = new ServerSocket(4242); System.out.printf("Server open. Waiting for connections on %s\n", serverSocket); //wait for connections while (true) { Socket socket = serverSocket.accept(); System.out.printf("Connection established with %s\n", socket); MessagingServer server = new MessagingServer(socket); //when thread starts to run, we can find the run method in the MessagingServer class //the socket is also already initialized in that class new Thread(server).start(); } } catch (IOException e) { System.out.println("Could not establish connection with client"); e.printStackTrace(); return; } } public void run() { //read in all the taken ids try { readUsedIDs(); initializeCustomerGatekeepers(); } catch (IOException e) { e.printStackTrace(); return; } ObjectOutputStream oos; //to write objects to client ObjectInputStream ois; //to read objects from client int choice; //verifies user's choice for each menu try { oos = new ObjectOutputStream(socket.getOutputStream()); ois = new ObjectInputStream(socket.getInputStream()); oos.flush(); do { try { choice = startPageProcessing(oos, ois); //end the thread if choice = 0; if (choice == 0) { System.out.println("Error in reading user info!"); return; } else if (choice == 1) { //start seller menu processing sellerMenuProcessing(oos, ois); } else if (choice == 2) { //start customer menu processing customerMenuProcessing(oos, ois); } } catch (EOFException e) { //checks if user closes the app System.out.printf("Connection with %s ended.\n", socket); return; } catch (SocketException e) { System.out.printf("Connection with %s ended.\n", socket); return; } } while (true); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } //creates the logic for the start page //if return 0 -> user info array is null //if return 1 -> it's a seller //if return 2 -> it's a customer //it throws an EOFException public int startPageProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { int choice; //checks what the user does - sign in, sign up or quit do { //first read in the choice choice = ois.readInt(); //sign in if (choice == 0) { String[] signInDetails = (String[]) ois.readObject(); String email = signInDetails[0]; String password = signInDetails[1]; User user = new User(); //checks user's credentials, returns //0 - if email is not found //1 - if password is incorrect //2 - if everything is correct int check = user.checkCredentials(email, password); if (check == 0) { oos.writeInt(0); oos.flush(); } else if (check == 1) { oos.writeInt(1); oos.flush(); } else { String[] userInfo = null; synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { if (line.split(",")[1].equals(email)) { userInfo = line.split(","); break; } line = br.readLine(); } } } oos.writeInt(2); oos.flush(); oos.writeObject(userInfo); if (userInfo == null) { return 0; } else if (userInfo[3].equalsIgnoreCase("seller")) { seller = new Seller(userInfo[0], userInfo[1], userInfo[2], userInfo[3]); return 1; } else { customer = new Customer(userInfo[0], userInfo[1], userInfo[2], userInfo[3]); return 2; } } } else if (choice == 1) { boolean navigation = true; //sign up if (ois.readInt() == 0) { continue; } String[] signUpDetails = (String[]) ois.readObject(); String name = signUpDetails[0]; String email = signUpDetails[1]; String password = signUpDetails[2]; String rePass = signUpDetails[3]; String userType = signUpDetails[4]; String uniqueID; if (userType.equalsIgnoreCase("customer")) { int check; do { check = checkSignUp(name, email, password, rePass); oos.writeInt(check); oos.flush(); if (check != 0) { if (ois.readInt() == 0) { navigation = false; break; } signUpDetails = (String[]) ois.readObject(); name = signUpDetails[0]; email = signUpDetails[1]; password = signUpDetails[2]; rePass = signUpDetails[3]; userType = signUpDetails[4]; } } while (check != 0); if (navigation) { customer = new Customer(name, email, password, userType); uniqueID = customer.getCustomerID(); synchronized (USER_DETAILS_GATEKEEPER) { try (PrintWriter pw = new PrintWriter( new FileOutputStream("loginDetails.txt", true))) { pw.printf("%s,%s,%s,%s,%s\n", name, email, password, userType.toLowerCase(), uniqueID); } } //add to gatekeeper MessagingServer.CUSTOMER_GATEKEEPERS.add(new Customer(name, email, password, userType)); } } else if (userType.equalsIgnoreCase("seller")) { int check; do { check = checkSignUp(name, email, password, rePass); oos.writeInt(check); oos.flush(); if (check != 0) { if (ois.readInt() == 0) { navigation = false; break; } signUpDetails = (String[]) ois.readObject(); name = signUpDetails[0]; email = signUpDetails[1]; password = signUpDetails[2]; rePass = signUpDetails[3]; userType = signUpDetails[4]; } } while (check != 0); if (navigation) { seller = new Seller(name, email, password, userType); uniqueID = seller.getSellerID(); synchronized (USER_DETAILS_GATEKEEPER) { try (PrintWriter pw = new PrintWriter( new FileOutputStream("loginDetails.txt", true))) { pw.printf("%s,%s,%s,%s,%s\n", name, email, password, userType.toLowerCase(), uniqueID); } } } } } } while (true); } public int checkSignUp(String name, String email, String password, String rePass) { try { if (User.isNameValid(name) != 0) { return (User.isNameValid(name)); // 1 for empty name String, 2 for invalid character in name String } else if (!User.isEmailValid(email)) { return 3; // 3 for invalid email format } else if (!User.isEmailUnique(email)) { return 4; // 4 for occupied email } else if (!User.isPasswordValid(password)) { return 5; // 5 for invalid password format } else if (!password.equals(rePass)) { return 6; // 6 for password and re-enter password doesn't match } else { return 0; // 0 if it passes the test } } catch (IOException e) { return 7; //7 for IO Exception } } //have to update seller info for every menu public void updateSellerInfo() throws IOException { String[] lineSplit = null; synchronized (USER_DETAILS_GATEKEEPER) { //updates seller details and stores try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { if (line.split(",")[4].equals(seller.getSellerID())) { lineSplit = line.split(","); break; } line = br.readLine(); } } catch (FileNotFoundException e) { //don't do anything } } //reconstruct a new seller, this ensures all info is up-to-date //stores are also updated here. if (lineSplit != null) { seller = new Seller(lineSplit[0], lineSplit[1], lineSplit[2], lineSplit[3]); } else { System.out.println("Error in updateSellerInfo"); } } //have to update customer info for every menu public void updateCustomerInfo() throws IOException { String[] lineSplit = null; synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { if (line.split(",")[4].equals(customer.getCustomerID())) { lineSplit = line.split(","); break; } line = br.readLine(); } } catch (FileNotFoundException e) { //don't do anything } } //reconstruct a new seller, this ensures all info is up-to-date //stores are also updated here. if (lineSplit != null) { customer = new Customer(lineSplit[0], lineSplit[1], lineSplit[2], lineSplit[3]); } else { System.out.println("Error in updateCustomerInfo"); } } public void sellerMenuProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { //1 to enter new message menu processing //2 to enter store dashboard menu processing //3 to enter most common words menu //4 to enter create store menu processing //5 to enter view customer menu processing //6 to search for customer menu processing //7 to enter modify account processing do { updateSellerInfo(); oos.writeInt(User.getNewMsgCountTotal(seller.getSellerID()) + User.getDisapMsgCountTotal(seller.getSellerID())); oos.flush(); int choice = ois.readInt(); if (choice == 0) { return; } else if (choice == 1) { newMessageProcessingSeller(oos, ois); } else if (choice == 2) { statsProcessingSeller(oos, ois); } else if (choice == 4) { createStoreProcessing(oos, ois); } else if (choice == 5) { viewCustomerProcessing(oos, ois); } else if (choice == 6) { searchCustomerProcessing(oos, ois); } else if (choice == 7) { if (modAccountProcessing(oos, ois) == -1) { break; } } } while (true); } public void newMessageProcessingSeller(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { //read in an array list of customers ArrayList customers = readCustomers(); ArrayList sellerStores = seller.getStores(); ArrayList newMessages = new ArrayList<>(); for (Store store : sellerStores) { for (Customer cust : customers) { int newMsgCount = User.getNewMsgCountPerStore(store.getStoreID(), cust.getCustomerID()); if (newMsgCount != 0) { newMessages.add(new NewMessage(cust, store, newMsgCount)); } } } String[] sellerNewMessages = new String[newMessages.size()]; for (int i = 0; i < sellerNewMessages.length; i++) { sellerNewMessages[i] = String.format("Store %s with Customer %s : %d new messages", newMessages.get(i).getStore().getStoreName(), newMessages.get(i).getCustomer().getFullName(), newMessages.get(i).getCountOfNewMessages()); } oos.writeObject(sellerNewMessages); oos.flush(); int choice = ois.readInt(); if (choice == 0) { return; } else if (choice == -10) { continue; } int newMessageChoice = ois.readInt(); sellerMessagingMenuProcessing(newMessages.get(newMessageChoice).getCustomer(), newMessages.get(newMessageChoice).getStore(), oos, ois); } while (true); } public void statsProcessingSeller(ObjectOutputStream oos, ObjectInputStream ois) throws IOException { do { String[] storeNames = new String[seller.getStores().size()]; for (int i = 0; i < storeNames.length; i++) { storeNames[i] = seller.getStores().get(i).getStoreName(); } oos.writeObject(storeNames); oos.flush(); if (ois.readInt() == 0) { return; } int storeChoice = ois.readInt(); Store storeToUse = seller.getStores().get(storeChoice); do { //send most common words info mostCommonWordsProcessing(oos, storeToUse); //get an arraylist of customers ArrayList customers = new ArrayList<>(); synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { String[] splitLine = line.split(","); if (splitLine[3].equals("customer")) { customers.add(new Customer(splitLine[0], splitLine[1], splitLine[3], splitLine[4])); } line = br.readLine(); } } } ArrayList count = storeToUse.getStoreMessageCounts(customers); String[] storeStats = new String[count.size()]; for (int i = 0; i < count.size(); i++) { storeStats[i] = String.format("Store %s with Customer %s (%d messages received)", storeToUse.getStoreName(), customers.get(i).getFullName(), count.get(i)); } oos.writeObject(storeStats); oos.flush(); if (sortingStatsSeller(oos, ois, storeStats, count) == 0) { break; } } while (true); } while (true); } public int sortingStatsSeller(ObjectOutputStream oos, ObjectInputStream ois, String[] storeStats, ArrayList count) throws IOException { do { //1 default //2 - increasing //3 - decreasing int choice = ois.readInt(); if (choice == 0) { return 0; } else if (choice == -1) { return -1; } else if (choice == 1) { oos.writeObject(storeStats); oos.flush(); } else { oos.writeObject(Store.sortStoreStats(storeStats, count, choice)); oos.flush(); } } while (true); } public void mostCommonWordsProcessing(ObjectOutputStream oos, Store chosenStore) throws IOException { ArrayList words = new ArrayList<>(); ArrayList wordCount = new ArrayList<>(); ArrayList customers = readCustomers(); for (Customer cust : customers) { try (BufferedReader br = new BufferedReader( new FileReader(String.format("%s_%s.txt", chosenStore.getStoreID(), cust.getCustomerID())))) { String line = br.readLine(); while (line != null) { line = br.readLine(); String noPuncLine = line.replaceAll("\\p{Punct}", "").toLowerCase(); for (String word : noPuncLine.split(" ")) { if (!words.contains(word)) { words.add(word); wordCount.add(1); } else { int indexToAdd = words.indexOf(word); wordCount.set(indexToAdd, wordCount.get(indexToAdd) + 1); } } line = br.readLine(); } } catch (FileNotFoundException e) { //don't do anything } try (BufferedReader br = new BufferedReader( new FileReader(String.format("%s_%s_new.txt", chosenStore.getStoreID(), cust.getCustomerID())))) { String line = br.readLine(); while (line != null) { line = br.readLine(); String noPuncLine = line.replaceAll("\\p{Punct}", "").toLowerCase(); for (String word : noPuncLine.split(" ")) { if (!words.contains(word)) { words.add(word); wordCount.add(1); } else { int indexToAdd = words.indexOf(word); wordCount.set(indexToAdd, wordCount.get(indexToAdd) + 1); } } line = br.readLine(); } } catch (FileNotFoundException e) { //don't do anything } } if (words.size() != wordCount.size()) { System.out.println("Error in mostCommonWordsProcessing"); return; } if (words.size() == 0) { oos.writeObject(new String[0]); oos.flush(); return; } ArrayList wordCountsToReturn = new ArrayList<>(); int wordsAdded = 0; while (wordsAdded < words.size() || wordsAdded < 10) { int maxIndex = findMaxIndex(wordCount); wordCountsToReturn.add(words.get(maxIndex)); wordCountsToReturn.add(String.valueOf(wordCount.get(maxIndex))); wordsAdded++; words.remove(maxIndex); wordCount.remove(maxIndex); if (words.size() == 0) { break; } } String[] toReturn = new String[wordCountsToReturn.size()]; wordCountsToReturn.toArray(toReturn); oos.writeObject(toReturn); oos.flush(); } public int findMaxIndex(ArrayList counts) { if (counts == null) { return -1; } int max = 0; int index = 0; for (Integer count : counts) { if (count > max) { max = count; index = counts.indexOf(count); } } return index; } public int modAccountProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { boolean invalidInfoCheck = false; int choice = ois.readInt(); if (choice == 0) { return 0; } if (choice == -1) { if (seller != null) { User.deleteUserAccount(seller.getSellerID()); return -1; } else { User.deleteUserAccount(customer.getCustomerID()); return -1; } } String[] userInfo = (String[]) ois.readObject(); String name = userInfo[0]; String email = userInfo[1]; String password = userInfo[2]; String rePass = userInfo[3]; String userID = userInfo[4]; String nameEmergency = ""; String emailEmergency = ""; String passwordEmergency = ""; String userTypeEmergency = ""; //first remove user detail from file synchronized (USER_DETAILS_GATEKEEPER) { String file = ""; try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { if (line.split(",")[4].equals(userID)) { if (userID.contains("SELLER")) { userTypeEmergency = "seller"; } else { userTypeEmergency = "customer"; } nameEmergency = line.split(",")[0]; emailEmergency = line.split(",")[1]; passwordEmergency = line.split(",")[2]; line = br.readLine(); continue; } file += line + "\n"; line = br.readLine(); } } try (PrintWriter pw = new PrintWriter(new FileOutputStream("loginDetails.txt"))) { pw.print(file); } } do { int check; if (invalidInfoCheck) { choice = ois.readInt(); if (choice == 0) { try (PrintWriter pw = new PrintWriter( new FileOutputStream("loginDetails.txt", true))) { pw.printf("%s,%s,%s,%s,%s\n", nameEmergency, emailEmergency, passwordEmergency, userTypeEmergency, userID); } return 0; } if (choice == -1) { if (seller != null) { User.deleteUserAccount(seller.getSellerID()); return -1; } else { User.deleteUserAccount(customer.getCustomerID()); return -1; } } userInfo = (String[]) ois.readObject(); name = userInfo[0]; email = userInfo[1]; password = userInfo[2]; rePass = userInfo[3]; userID = userInfo[4]; //first remove user detail from file synchronized (USER_DETAILS_GATEKEEPER) { String file = ""; try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { if (line.contains(userID)) { line = br.readLine(); continue; } file += line + "\n"; line = br.readLine(); } } try (PrintWriter pw = new PrintWriter(new FileOutputStream("loginDetails.txt"))) { pw.print(file); } } } check = checkSignUp(name, email, password, rePass); oos.writeInt(check); oos.flush(); if (check != 0) { invalidInfoCheck = true; } else { String userType; if (userID.contains("SELLER")) { userType = "seller"; } else { userType = "customer"; } try (PrintWriter pw = new PrintWriter(new FileOutputStream("loginDetails.txt", true))) { pw.printf("%s,%s,%s,%s,%s\n", name, email, password, userType, userID); } if (userID.contains("SELLER")) { updateSellerInfo(); } else { if (!name.equals(customer.getFullName())) { changeMessageFileNamesCustomer(name); } updateCustomerInfo(); } break; } } while (true); } while (true); } public void changeMessageFileNamesCustomer(String newName) throws IOException { ArrayList stores = readStores(); for (Store store : stores) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { String file = ""; try (BufferedReader br = new BufferedReader(new FileReader( String.format("%s_%s.txt", store.getStoreID(), customer.getCustomerID())))) { int lineNumber = 1; String line = br.readLine(); while (line != null) { if (lineNumber % 2 != 0 && line.split(",")[0].equals(customer.getFullName())) { String[] lineSplit = line.split(","); lineSplit[0] = newName; file += String.join(",", lineSplit) + "\n"; lineNumber++; line = br.readLine(); continue; } file += line + "\n"; lineNumber++; line = br.readLine(); } } catch (FileNotFoundException e) { continue; } try (PrintWriter pw = new PrintWriter(new FileOutputStream( String.format("%s_%s.txt", store.getStoreID(), customer.getCustomerID())))) { pw.print(file); } } } for (Store store : stores) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { String file = ""; try (BufferedReader br = new BufferedReader(new FileReader( String.format("%s_%s.txt", customer.getCustomerID(), store.getStoreID())))) { int lineNumber = 1; String line = br.readLine(); while (line != null) { if (lineNumber % 2 != 0 && line.split(",")[0].equals(customer.getFullName())) { String[] lineSplit = line.split(","); lineSplit[0] = newName; file += String.join(",", lineSplit) + "\n"; lineNumber++; line = br.readLine(); continue; } file += line + "\n"; lineNumber++; line = br.readLine(); } } catch (FileNotFoundException e) { continue; } try (PrintWriter pw = new PrintWriter(new FileOutputStream( String.format("%s_%s.txt", customer.getCustomerID(), store.getStoreID())))) { pw.print(file); } } } for (Store store : stores) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { String file = ""; try (BufferedReader br = new BufferedReader(new FileReader( String.format("%s_%s_new.txt", customer.getCustomerID(), store.getStoreID())))) { int lineNumber = 1; String line = br.readLine(); while (line != null) { if (lineNumber % 2 != 0 && line.split(",")[0].equals(customer.getFullName())) { String[] lineSplit = line.split(","); lineSplit[0] = newName; file += String.join(",", lineSplit) + "\n"; lineNumber++; line = br.readLine(); continue; } file += line + "\n"; lineNumber++; line = br.readLine(); } } catch (FileNotFoundException e) { continue; } try (PrintWriter pw = new PrintWriter(new FileOutputStream( String.format("%s_%s_new.txt", customer.getCustomerID(), store.getStoreID())))) { pw.print(file); } } } for (Store store : stores) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { String file = ""; try (BufferedReader br = new BufferedReader(new FileReader( String.format("%s_%s_new.txt", store.getStoreID(), customer.getCustomerID())))) { int lineNumber = 1; String line = br.readLine(); while (line != null) { if (lineNumber % 2 != 0 && line.split(",")[0].equals(customer.getFullName())) { String[] lineSplit = line.split(","); lineSplit[0] = newName; file += String.join(",", lineSplit) + "\n"; lineNumber++; line = br.readLine(); continue; } file += line + "\n"; lineNumber++; line = br.readLine(); } } catch (FileNotFoundException e) { continue; } try (PrintWriter pw = new PrintWriter(new FileOutputStream( String.format("%s_%s_new.txt", store.getStoreID(), customer.getCustomerID())))) { pw.print(file); } } } } public void createStoreProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { String[] storeDetails; do { int choice = ois.readInt(); if (choice == 0) { return; } storeDetails = (String[]) ois.readObject(); if (Store.isStoreNameUnique(storeDetails[0])) { oos.writeInt(1); oos.flush(); break; } oos.writeInt(-1); oos.flush(); } while (true); new Store(storeDetails[0], storeDetails[1], seller.getSellerID(), seller.getFullName()).writeStoreToFile(); updateSellerInfo(); } //returns an array list of all customers public ArrayList readCustomers() throws IOException { ArrayList customers = new ArrayList<>(); synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { String line = br.readLine(); while (line != null) { String[] lineSplit = line.split(","); if (lineSplit[3].equals("customer")) { customers.add(new Customer(lineSplit[0], lineSplit[1], lineSplit[2], lineSplit[3])); } line = br.readLine(); } } } return customers; } //handles the search for customer feature public void searchCustomerProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { updateSellerInfo(); int choice = ois.readInt(); if (choice == 0) { return; } //read search string String search = (String) ois.readObject(); ArrayList customerMatches = searchForCustomers(seller, search); String[] customerMatchesNames = new String[customerMatches.size()]; for (int i = 0; i < customerMatchesNames.length; i++) { customerMatchesNames[i] = customerMatches.get(i).getFullName(); } String[] storeNames = new String[seller.getStores().size()]; for (int i = 0; i < storeNames.length; i++) { storeNames[i] = seller.getStores().get(i).getStoreName(); } // if (storeNames.length == 0 || customerMatchesNames.length == 0) { // continue; // } do { oos.writeObject(customerMatchesNames); oos.flush(); oos.writeObject(storeNames); oos.flush(); choice = ois.readInt(); if (choice == 0) { break; } int customerChoice = ois.readInt(); Customer customerChosen = customerMatches.get(customerChoice); int storeChoice = ois.readInt(); Store chosenStore = seller.getStores().get(storeChoice); sellerMessagingMenuProcessing(customerChosen, chosenStore, oos, ois); } while (true); } while (true); } // the helper method to search for a customer, returns an array list of customer matches, already checks // for invisibility status here public ArrayList searchForCustomers(Seller myself, String customerName) throws IOException { ArrayList customerMatches = new ArrayList<>(); ArrayList customers = readCustomers(); for (Customer cust : customers) { if (cust.getFullName().toLowerCase().contains(customerName.toLowerCase())) { if (!User.areTheyInvisible(myself.getSellerID(), cust.getCustomerID())) { customerMatches.add(cust); } } } return customerMatches; } //handles the features to view customers public void viewCustomerProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { //1: next //0: return updateSellerInfo(); //send customer info ArrayList customers = readCustomers(); //send array of customer names to client ArrayList customerNames = new ArrayList<>(); for (Customer cust : customers) { customerNames.add(cust.getFullName()); } String[] namesToSend = new String[customerNames.size()]; customerNames.toArray(namesToSend); oos.writeObject(namesToSend); oos.flush(); //send store info ArrayList storeNames = new ArrayList<>(); for (Store store : seller.getStores()) { storeNames.add(store.getStoreName()); } String[] storesToSend = new String[storeNames.size()]; storeNames.toArray(storesToSend); oos.writeObject(storesToSend); oos.flush(); int choice = ois.readInt(); if (choice == 0) { return; } if (storesToSend.length == 0 || namesToSend.length == 0) { return; } int customerChoice = ois.readInt(); //index of customer chosen by the client Customer customerChosen = customers.get(customerChoice); int storeChoice = ois.readInt(); Store chosenStore = seller.getStores().get(storeChoice); sellerMessagingMenuProcessing(customerChosen, chosenStore, oos, ois); } while (true); } //the messaging menu for sellers public void sellerMessagingMenuProcessing( Customer cust, Store store, ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { //if they are blocked - send 1, else send 0 if (User.areTheyBlocked(store.getStoreID(), cust.getCustomerID())) { oos.writeInt(1); oos.flush(); } else { oos.writeInt(0); oos.flush(); } //if I am invisible to them, send 1, else send 0 if (User.isInvisible(store.getStoreID(), cust.getCustomerID())) { oos.writeInt(1); oos.flush(); } else { oos.writeInt(0); oos.flush(); } oos.writeObject(cust.getFullName()); oos.flush(); ArrayList messages; synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { messages = User.getMsg(store.getStoreID(), cust.getCustomerID()); } if (messages.size() == 0) { oos.writeObject(new String[0]); oos.flush(); } else { ArrayList messageInfo = new ArrayList<>(); for (int i = 0; i < messages.size(); i++) { if (i == 0 && messages.get(i).getIsNew()) { messageInfo.add("---------------------------------------" + "NEW MESSAGES BELOW----------------------------------------"); messageInfo.add(messages.get(i).toString()); continue; } if (i + 1 < messages.size()) { if (!messages.get(i).getIsNew() && messages.get(i + 1).getIsNew()) { messageInfo.add(messages.get(i).toString()); messageInfo.add("---------------------------------------" + "NEW MESSAGES BELOW----------------------------------------"); continue; } } messageInfo.add(messages.get(i).toString()); } synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.flushMsg(store.getStoreID(), cust.getCustomerID()); } String[] messageInfoToSend = new String[messageInfo.size()]; messageInfo.toArray(messageInfoToSend); oos.writeObject(messageInfoToSend); oos.flush(); } //message menu choices: int choice = ois.readInt(); if (choice == 0) { return; } else if (choice == 1) { if (User.isBlocked(store.getStoreID(), cust.getCustomerID())) { oos.writeInt(-1); oos.flush(); continue; } else { oos.writeInt(1); oos.flush(); } //-1 back //0 regular //1 regular disappearing //2 file import regular //3 file import disappearing int msgType = ois.readInt(); if (msgType == -1) { continue; } else if (msgType == 0) { String messageContent = (String) ois.readObject(); //send a regular message synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.sendMsg(new Message(store.getStoreName(), store.getStoreID(), messageContent, LocalDateTime.now().toString(), false, true), cust.getCustomerID()); } } else if (msgType == 1) { String messageContent = (String) ois.readObject(); //send a disappearing message synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.sendMsg(new Message(store.getStoreName(), store.getStoreID(), messageContent, LocalDateTime.now().toString(), true, true), cust.getCustomerID()); } } else if (msgType == 2) { //send a regular file import String[] fileMessage = (String[]) ois.readObject(); if (fileMessage == null) { continue; } for (String line : fileMessage) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.sendMsg(new Message(store.getStoreName(), store.getStoreID(), line, LocalDateTime.now().toString(), false, true), cust.getCustomerID()); } } } else if (msgType == 3) { //send a disappearing file import String[] fileMessage = (String[]) ois.readObject(); if (fileMessage == null) { continue; } for (String line : fileMessage) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.sendMsg(new Message(store.getStoreName(), store.getStoreID(), line, LocalDateTime.now().toString(), true, true), cust.getCustomerID()); } } } } else if (choice == 2) { //0 - back //1 - edit Message[] messagesToModify; synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { messagesToModify = User.messagesToModify(store.getStoreID(), cust.getCustomerID()); } String[] messagesToSend = new String[messagesToModify.length]; for (int i = 0; i < messagesToSend.length; i++) { messagesToSend[i] = messagesToModify[i].toString(); } oos.writeObject(messagesToSend); oos.flush(); if (messagesToSend.length == 0) { ois.readInt(); continue; } int toEdit = ois.readInt(); if (toEdit == 0) { continue; } int messageToEditIndex = ois.readInt(); Message messageToEdit = messagesToModify[messageToEditIndex]; String editedMessage = (String) ois.readObject(); synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.editMsg(editedMessage, messageToEdit, store.getStoreID(), cust.getCustomerID()); } } else if (choice == 3) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { String fileContents = ""; try (BufferedReader br = new BufferedReader(new FileReader(String.format("%s_%s.txt", store.getStoreID(), cust.getCustomerID())))) { String line = br.readLine(); while (line != null) { fileContents += line + "\n"; line = br.readLine(); } if (fileContents.equals("")) { oos.writeObject(""); oos.flush(); oos.writeObject(""); oos.flush(); } else { oos.writeObject(String.format("%s_%s.csv", store.getStoreID(), cust.getCustomerID())); oos.flush(); oos.writeObject(fileContents); oos.flush(); } } catch (FileNotFoundException e) { oos.writeObject(""); oos.flush(); oos.writeObject(""); oos.flush(); } } } else if (choice == 4) { //0 - back //1 - delete Message[] messagesToModify; synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { messagesToModify = User.messagesToModify(store.getStoreID(), cust.getCustomerID()); } String[] messagesToSend = new String[messagesToModify.length]; for (int i = 0; i < messagesToSend.length; i++) { messagesToSend[i] = messagesToModify[i].toString(); } oos.writeObject(messagesToSend); oos.flush(); int toDelete = ois.readInt(); if (toDelete == 0) { continue; } int messageToDeleteIndex = ois.readInt(); Message messageToDelete = messagesToModify[messageToDeleteIndex]; synchronized (Objects.requireNonNull(getCustomerGatekeeper(cust.getID()))) { User.deleteMsg(messageToDelete, store.getStoreID(), cust.getCustomerID()); } } else if (choice == 5) { synchronized (BLOCK_GATEKEEPER) { if (User.areTheyBlocked(store.getStoreID(), cust.getCustomerID())) { User.unblockUser(store.getStoreID(), cust.getCustomerID()); } else { User.blockUser(store.getStoreID(), cust.getCustomerID()); } } } else if (choice == 6) { synchronized (INVISIBLE_GATEKEEPER) { if (User.isInvisible(store.getStoreID(), cust.getCustomerID())) { User.becomeVisible(store.getStoreID(), cust.getCustomerID()); } else { User.becomeInvisible(store.getStoreID(), cust.getCustomerID()); } } } } while (true); } public ArrayList readSellers() throws IOException { ArrayList sellers = new ArrayList<>(); String line; synchronized (USER_DETAILS_GATEKEEPER) { try (BufferedReader br = new BufferedReader(new FileReader("loginDetails.txt"))) { do { line = br.readLine(); if (line == null) { break; } String[] lineSplit = line.split(","); if (lineSplit[3].equals("seller")) { sellers.add(new Seller(lineSplit[0], lineSplit[1], lineSplit[2], lineSplit[3])); } } while (true); } } return sellers; } //read in stores from a file public ArrayList readStores() throws IOException { String line; ArrayList stores = new ArrayList<>(); try (BufferedReader br = new BufferedReader(new FileReader("stores.txt"))) { do { line = br.readLine(); if (line == null) { break; } String[] lineSplit = line.split(","); stores.add(new Store(lineSplit[0], lineSplit[1], lineSplit[2], lineSplit[4])); } while (true); } catch (FileNotFoundException e) { //no need to throw any errors if file is not found } return stores; } public void customerMenuProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { //1 to enter new message menu processing //2 to enter statistics menu processing //3 to enter view stores menu processing //4 to search for seller menu processing //5 to enter modify account processing do { updateCustomerInfo(); oos.writeInt(User.getNewMsgCountTotal(customer.getCustomerID()) + User.getDisapMsgCountTotal(customer.getCustomerID())); oos.flush(); int choice = ois.readInt(); if (choice == 0) { return; } else if (choice == 1) { newMessageProcessingCustomer(oos, ois); } else if (choice == 2) { statsProcessingCustomer(oos, ois); } else if (choice == 3) { viewStoresMenuProcessing(oos, ois); } else if (choice == 4) { searchSellerProcessing(oos, ois); } else if (choice == 5) { if (modAccountProcessing(oos, ois) == -1) { return; } } } while (true); } public void newMessageProcessingCustomer(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { //read in an array list of stores ArrayList stores = readStores(); ArrayList newMessages = new ArrayList<>(); for (Store store : stores) { int newMsgCount = User.getNewMsgCountPerStore(customer.getCustomerID(), store.getStoreID()); if (newMsgCount != 0) { newMessages.add(new NewMessage(customer, store, newMsgCount)); } } String[] customerNewMessages = new String[newMessages.size()]; for (int i = 0; i < customerNewMessages.length; i++) { customerNewMessages[i] = String.format("Conversation with Store %s owned by %s: %d new messages", newMessages.get(i).getStore().getStoreName(), newMessages.get(i).getStore().getSellerName(), newMessages.get(i).getCountOfNewMessages()); } oos.writeObject(customerNewMessages); oos.flush(); int choice = ois.readInt(); if (choice == 0) { return; } else if (choice == -10) { continue; } int newMessageChoice = ois.readInt(); customerMessagingMenuProcessing(newMessages.get(newMessageChoice).getStore(), oos, ois); } while (true); } public void statsProcessingCustomer(ObjectOutputStream oos, ObjectInputStream ois) throws IOException { do { ArrayList stores = readStores(); ArrayList countOfMessagesSent = customer.getNumMsgSentToStores(stores); ArrayList countOfMessagesReceived = customer.getNumMsgReceivedFromStores(stores); if (countOfMessagesReceived.size() != stores.size() || countOfMessagesSent.size() != stores.size()) { System.out.println("Error in statsProcessingCustomer"); return; } String[] messagesSentToStores = new String[countOfMessagesSent.size()]; for (int i = 0; i < messagesSentToStores.length; i++) { messagesSentToStores[i] = String.format("Total number of messages sent to %s: %d", stores.get(i).getStoreName(), countOfMessagesSent.get(i)); } String[] messagesReceivedFromStores = new String[countOfMessagesReceived.size()]; for (int i = 0; i < messagesReceivedFromStores.length; i++) { messagesReceivedFromStores[i] = String.format("Total number of messages received from %s: %d", stores.get(i).getStoreName(), countOfMessagesReceived.get(i)); } oos.writeObject(messagesSentToStores); oos.flush(); oos.writeObject(messagesReceivedFromStores); oos.flush(); if (sortingCustomerStats(countOfMessagesSent, messagesSentToStores, countOfMessagesReceived, messagesReceivedFromStores, oos, ois) == 0) { break; } } while (true); } public int sortingCustomerStats(ArrayList countOfMessagesSent, String[] messagesSentToStores, ArrayList countOfMessagesReceived, String[] messagesReceivedFromStores, ObjectOutputStream oos, ObjectInputStream ois) throws IOException { //1 - default //2 - increasing //3 - decreasing do { int choice = ois.readInt(); if (choice == 0) { return 0; } else if (choice == 1) { oos.writeObject(messagesSentToStores); } else if (choice == 2) { oos.writeObject(Customer.sortMessagesSent(countOfMessagesSent, messagesSentToStores, choice)); } else if (choice == 3) { oos.writeObject(Customer.sortMessagesSent(countOfMessagesSent, messagesSentToStores, choice)); } else if (choice == 4) { oos.writeObject(messagesReceivedFromStores); } else if (choice == 5) { oos.writeObject(Customer.sortMessagesReceived(countOfMessagesReceived, messagesReceivedFromStores, choice)); } else if (choice == 6) { oos.writeObject(Customer.sortMessagesReceived(countOfMessagesReceived, messagesReceivedFromStores, choice)); } else if (choice == -1) { return -1; } oos.flush(); } while (true); } public void viewStoresMenuProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { //1: next //0: return updateCustomerInfo(); //send store info ArrayList stores = readStores(); ArrayList storeNames = new ArrayList<>(); for (Store store : stores) { storeNames.add(store.getStoreName()); } String[] storesToSend = new String[storeNames.size()]; storeNames.toArray(storesToSend); oos.writeObject(storesToSend); oos.flush(); int choice = ois.readInt(); if (choice == 0) { return; } if (storesToSend.length == 0) { return; } int storeChoice = ois.readInt(); Store chosenStore = stores.get(storeChoice); customerMessagingMenuProcessing(chosenStore, oos, ois); } while (true); } //scans sellers list to retrieve sellers that match search description //returns an ArrayList of matches public ArrayList searchForSeller(Customer myself, String sellerName) throws IOException { ArrayList sellerMatches = new ArrayList<>(); ArrayList sellers = readSellers(); for (Seller sell : sellers) { if (sell.getFullName().toLowerCase().contains(sellerName.toLowerCase())) { if (!User.areTheyInvisible(myself.getCustomerID(), sell.getSellerID())) { sellerMatches.add(sell); } } } return sellerMatches; } public void searchSellerProcessing(ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { updateCustomerInfo(); int choice = ois.readInt(); if (choice == 0) { return; } //read search string String search = (String) ois.readObject(); //returns list of seller who are not invis to me ArrayList sellerMatches = searchForSeller(customer, search); ArrayList matches = new ArrayList<>(); ArrayList stores = new ArrayList<>(); for (Seller sell : sellerMatches) { for (Store store : sell.getStores()) { //indexes of both arraylists will match matches.add(String.format("%s - %s", sell.getFullName(), store.getStoreName())); stores.add(store); //used to keep track of what store/seller combo the user picks } } String[] matchesToSend = new String[matches.size()]; matches.toArray(matchesToSend); // if (storeNames.length == 0 || customerMatchesNames.length == 0) { // continue; // } do { oos.writeObject(matchesToSend); oos.flush(); int backNext = ois.readInt(); if (backNext == 0) { break; } int sellerStoreChoice = ois.readInt(); Store storeToUse = stores.get(sellerStoreChoice); customerMessagingMenuProcessing(storeToUse, oos, ois); } while (true); } while (true); } public void customerMessagingMenuProcessing(Store store, ObjectOutputStream oos, ObjectInputStream ois) throws IOException, ClassNotFoundException { do { //if they are blocked - send 1, else send 0 if (User.areTheyBlocked(customer.getCustomerID(), store.getStoreID())) { oos.writeInt(1); oos.flush(); } else { oos.writeInt(0); oos.flush(); } //if I am invisible to them, send 1, else send 0 if (User.isInvisible(customer.getCustomerID(), store.getStoreID())) { oos.writeInt(1); oos.flush(); } else { oos.writeInt(0); oos.flush(); } oos.writeObject(store.getStoreName()); oos.flush(); oos.writeObject(store.getSellerName()); oos.flush(); ArrayList messages = null; synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { messages = User.getMsg(customer.getCustomerID(), store.getStoreID()); } if (messages.size() == 0) { oos.writeObject(new String[0]); oos.flush(); } else { ArrayList messageInfo = new ArrayList<>(); for (int i = 0; i < messages.size(); i++) { if (i == 0 && messages.get(i).getIsNew()) { messageInfo.add("---------------------------------------" + "NEW MESSAGES BELOW----------------------------------------"); messageInfo.add(messages.get(i).toString()); continue; } if (i + 1 < messages.size()) { if (!messages.get(i).getIsNew() && messages.get(i + 1).getIsNew()) { messageInfo.add(messages.get(i).toString()); messageInfo.add("---------------------------------------" + "NEW MESSAGES BELOW----------------------------------------"); continue; } } messageInfo.add(messages.get(i).toString()); } synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.flushMsg(customer.getCustomerID(), store.getStoreID()); } String[] messageInfoToSend = new String[messageInfo.size()]; messageInfo.toArray(messageInfoToSend); oos.writeObject(messageInfoToSend); oos.flush(); } //message menu choices: int choice = ois.readInt(); if (choice == 0) { return; } else if (choice == 1) { if (User.isBlocked(customer.getCustomerID(), store.getStoreID())) { oos.writeInt(-1); oos.flush(); continue; } else { oos.writeInt(1); oos.flush(); } //-1 back //0 regular //1 regular disappearing //2 file import regular //3 file import disappearing int msgType = ois.readInt(); if (msgType == -1) { continue; } else if (msgType == 0) { String messageContent = (String) ois.readObject(); //send a regular message synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.sendMsg(new Message(customer.getFullName(), customer.getCustomerID(), messageContent, LocalDateTime.now().toString(), false, true), store.getStoreID()); } } else if (msgType == 1) { String messageContent = (String) ois.readObject(); //send a disappearing message synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.sendMsg(new Message(customer.getFullName(), customer.getCustomerID(), messageContent, LocalDateTime.now().toString(), true, true), store.getStoreID()); } } else if (msgType == 2) { //send a regular file import String[] fileMessage = (String[]) ois.readObject(); if (fileMessage == null) { continue; } for (String line : fileMessage) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.sendMsg(new Message(customer.getFullName(), customer.getCustomerID(), line, LocalDateTime.now().toString(), false, true), store.getStoreID()); } } } else if (msgType == 3) { //send a disappearing file import String[] fileMessage = (String[]) ois.readObject(); if (fileMessage == null) { continue; } for (String line : fileMessage) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.sendMsg(new Message(customer.getFullName(), customer.getCustomerID(), line, LocalDateTime.now().toString(), true, true), store.getStoreID()); } } } } else if (choice == 2) { //0 - back //1 - edit Message[] messagesToModify; synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { messagesToModify = User.messagesToModify(customer.getCustomerID(), store.getStoreID()); } String[] messagesToSend = new String[messagesToModify.length]; for (int i = 0; i < messagesToSend.length; i++) { messagesToSend[i] = messagesToModify[i].toString(); } oos.writeObject(messagesToSend); oos.flush(); if (messagesToSend.length == 0) { ois.readInt(); continue; } int toEdit = ois.readInt(); if (toEdit == 0) { continue; } int messageToEditIndex = ois.readInt(); Message messageToEdit = messagesToModify[messageToEditIndex]; String editedMessage = (String) ois.readObject(); synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.editMsg(editedMessage, messageToEdit, customer.getCustomerID(), store.getStoreID()); } } else if (choice == 3) { synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { String fileContents = ""; try (BufferedReader br = new BufferedReader(new FileReader(String.format( "%s_%s.txt", customer.getCustomerID(), store.getStoreID())))) { String line = br.readLine(); while (line != null) { fileContents += line + "\n"; line = br.readLine(); } if (fileContents.equals("")) { oos.writeObject(""); oos.flush(); oos.writeObject(""); oos.flush(); } else { oos.writeObject(String.format("%s_%s.csv", customer.getCustomerID(), store.getStoreID())); oos.flush(); oos.writeObject(fileContents); oos.flush(); } } catch (FileNotFoundException e) { oos.writeObject(""); oos.flush(); oos.writeObject(""); oos.flush(); } } } else if (choice == 4) { //0 - back //1 - delete Message[] messagesToModify; synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { messagesToModify = User.messagesToModify(customer.getCustomerID(), store.getStoreID()); } String[] messagesToSend = new String[messagesToModify.length]; for (int i = 0; i < messagesToSend.length; i++) { messagesToSend[i] = messagesToModify[i].toString(); } oos.writeObject(messagesToSend); oos.flush(); int toDelete = ois.readInt(); if (toDelete == 0) { continue; } int messageToDeleteIndex = ois.readInt(); Message messageToDelete = messagesToModify[messageToDeleteIndex]; synchronized (Objects.requireNonNull(getCustomerGatekeeper(customer.getID()))) { User.deleteMsg(messageToDelete, customer.getCustomerID(), store.getStoreID()); } } else if (choice == 5) { synchronized (BLOCK_GATEKEEPER) { if (User.areTheyBlocked(customer.getCustomerID(), store.getStoreID())) { User.unblockUser(customer.getCustomerID(), store.getStoreID()); } else { User.blockUser(customer.getCustomerID(), store.getStoreID()); } } } else if (choice == 6) { synchronized (INVISIBLE_GATEKEEPER) { if (User.isInvisible(customer.getCustomerID(), store.getStoreID())) { User.becomeVisible(customer.getCustomerID(), store.getStoreID()); } else { User.becomeInvisible(customer.getCustomerID(), store.getStoreID()); } } } } while (true); } }