diff --git a/app/src/main/java/itmo/lab5/App.java b/app/src/main/java/itmo/lab5/App.java index 69cdf39..5d93203 100644 --- a/app/src/main/java/itmo/lab5/App.java +++ b/app/src/main/java/itmo/lab5/App.java @@ -37,6 +37,7 @@ public class App { .register("history", new HistoryCommand()) .register("insert", new InsertCommand()) .register("update", new UpdateCommand()) + .register("save", new SaveCommand()) .build(); try { @@ -50,6 +51,7 @@ public class App { context.set("registry", registry); context.set("collection", flats); context.set("history", history); + context.set("path", dataFilePath.toString()); var scanner = new Scanner(System.in); diff --git a/app/src/main/java/itmo/lab5/cli/CommandInvoker.java b/app/src/main/java/itmo/lab5/cli/CommandInvoker.java new file mode 100644 index 0000000..1a9b5bb --- /dev/null +++ b/app/src/main/java/itmo/lab5/cli/CommandInvoker.java @@ -0,0 +1,29 @@ +package itmo.lab5.cli; + +import itmo.lab5.cli.helpers.History; +import itmo.lab5.interfaces.*; + +class CommandInvoker { + private final CommandRegistry registry; + private final CommandContext context; + private final History history; + + public CommandInvoker(CommandRegistry registry, CommandContext context, History history) { + this.registry = registry; + this.context = context; + this.history = history; + } + + public String executeCommand(String commandName, String[] args) { + Command command = registry.getByName(commandName); + if (command != null) { + history.add(commandName); + try { + return command.execute(args, context); + } catch (Exception e) { + return "Error executing command '" + commandName + "': " + e.getMessage(); + } + } + return "Unknown command: " + commandName; + } +} diff --git a/app/src/main/java/itmo/lab5/cli/commands/InsertCommand.java b/app/src/main/java/itmo/lab5/cli/commands/InsertCommand.java index 3ed366f..eae7b16 100644 --- a/app/src/main/java/itmo/lab5/cli/commands/InsertCommand.java +++ b/app/src/main/java/itmo/lab5/cli/commands/InsertCommand.java @@ -1,8 +1,10 @@ package itmo.lab5.cli.commands; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Scanner; +import java.util.function.Function; import itmo.lab5.cli.helpers.*; import itmo.lab5.cli.CommandContext; @@ -16,10 +18,14 @@ public class InsertCommand implements Command { @Override public String execute(String[] args, CommandContext context) { - if (args.length < 1) { - return "Usage: insert null {element}"; + if (args.length == 0) { + return executeInteractive(context); } + return executeWithArgs(args, context); + } + + private String executeInteractive(CommandContext context) { Date creationDate = new Date(); String name = inputReader.promptString("- Enter name: ", false, null); @@ -75,4 +81,125 @@ public class InsertCommand implements Command { return "New flat was successfully inserted!"; } + + private String executeWithArgs(String[] args, CommandContext context) { + HashMap params = new HashMap<>(); + + for (String arg : args) { + String[] parts = arg.split("=", 2); + if (parts.length == 2) { + params.put(parts[0], parts[1]); + } + } + + Date creationDate = new Date(); + String name = params.containsKey("name") ? params.get("name") + : inputReader.promptString("- Enter name: ", false, null); + + System.out.println("- Coordinates "); + int x = params.containsKey("x") ? Integer.parseInt(params.get("x")) + : inputReader.promptNumber("\t Enter x: ", Integer.MIN_VALUE, Integer.MAX_VALUE, Integer::parseInt, null); + Long y = params.containsKey("y") ? Long.parseLong(params.get("y")) + : inputReader.promptNumber("\t Enter y: ", Long.MIN_VALUE, Long.MAX_VALUE, Long::parseLong, null); + var coordinates = new Coordinates(x, y); + + Double area = params.containsKey("area") ? Double.parseDouble(params.get("area")) + : inputReader.promptNumber("\t Enter square: ", 0.0, 626.0, Double::parseDouble, null); + int numberOfRooms = params.containsKey("numberOfRooms") ? Integer.parseInt(params.get("numberOfRooms")) + : inputReader.promptNumber("\t Enter rooms count: ", 1, Integer.MAX_VALUE, Integer::parseInt, null); + + System.out.println("- Furnish"); + Furnish furnish = null; + if (params.containsKey("furnish")) { + String value = params.get("furnish").toUpperCase(); + while (!isValidEnumValue(Furnish.class, value)) { + System.out.println("Invalid furnish value: " + value + ". Please enter a valid furnish type."); + var t_furnish = inputReader.promptEnum("\t Enter furnish type: ", Furnish.class, null); + value = t_furnish.toString(); + } + furnish = (value.equalsIgnoreCase("NONE")) ? null : Furnish.valueOf(value); + } else { + furnish = inputReader.promptEnum("\t Enter furnish type: ", Furnish.class, null); + } + + System.out.println("- View"); + View view = null; + if (params.containsKey("view")) { + String value = params.get("view").toUpperCase(); + while (!isValidEnumValue(View.class, value)) { + System.out.println("Invalid view value: " + value + ". Please enter a valid view type."); + var t_view = (View) inputReader.promptEnum("\t Enter furnish type: ", View.class, null); + value = t_view.toString(); + } + view = (value.equalsIgnoreCase("NONE")) ? null : View.valueOf(value); + } else { + view = inputReader.promptEnumNullable("\t Enter view type: ", View.class, null); + } + + System.out.println("- Transport"); + Transport transport = null; + if (params.containsKey("transport")) { + String value = params.get("transport").toUpperCase(); + while (!isValidEnumValue(Transport.class, value)) { + System.out.println("Invalid transport value: " + value + ". Please enter a valid transport type."); + var t_trapsport = inputReader.promptEnum("\t Enter transport type: ", Transport.class, null); + value = t_trapsport.toString(); + } + transport = (value.equalsIgnoreCase("NONE")) ? null : Transport.valueOf(value); + } else { + transport = inputReader.promptEnum("\t Enter transport type: ", Transport.class, null); + } + + System.out.println("- House"); + String houseName = params.getOrDefault("houseName", ""); + if (houseName.isEmpty()) { + System.out.print("\t Enter house name: "); + houseName = scanner.nextLine().trim(); + } + + House house = null; + + if (!houseName.isEmpty()) { + int year = params.containsKey("houseYear") ? Integer.parseInt(params.get("houseYear")) + : inputReader.promptNumber("\t Enter house age: ", 1, 959, Integer::parseInt, null); + long floors = params.containsKey("houseFloors") ? Long.parseLong(params.get("houseFloors")) + : inputReader.promptNumber("\t Enter house floors count: ", 1L, 77L, Long::parseLong, null); + house = new House(houseName, year, floors); + } + + try { + HashMap collection = (HashMap) context.get("collection"); + int newID = collection.size() + 1; + Flat flat = new Flat( + newID, + name, + coordinates, + creationDate, + area, + numberOfRooms, + furnish, + view, + transport, + house); + + collection.put(newID, flat); + + } catch (ClassCastException e) { + return "There's an error while trying to add new element. Collection is broken."; + } + + return "New flat was successfully inserted!"; + } + + public static > boolean isValidEnumValue(Class enumClass, String value) { + if (value == null) + return false; + for (E constant : enumClass.getEnumConstants()) { + if (constant.name().equals(value)) { + return true; + } + } + return false; + } + } diff --git a/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java b/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java new file mode 100644 index 0000000..00c65bd --- /dev/null +++ b/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java @@ -0,0 +1,63 @@ +package itmo.lab5.cli.commands; + +import itmo.lab5.interfaces.Command; +import itmo.lab5.cli.*; +import itmo.lab5.models.*; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.BufferedWriter; +import java.util.HashMap; + +public class SaveCommand implements Command { + @Override + public String execute(String args[], CommandContext context) { + var collection = new HashMap(); + String filePath = null; + + try { + collection = (HashMap) context.get("collection"); + filePath = (String) context.get("path"); + } catch (ClassCastException e) { + return "Can't parse collection!"; + } + + if (filePath != null && collection != null) { + return saveCollectionToFile(collection, filePath); + } else { + return "Can't parse some object! Check filePath!"; + } + } + + public String saveCollectionToFile(HashMap flats, String filename) { + try (FileOutputStream fos = new FileOutputStream(filename); + OutputStreamWriter osw = new OutputStreamWriter(fos); + BufferedWriter writer = new BufferedWriter(osw)) { + + writer.write("id,name,x,y,area,numberOfRooms,furnish,view,transport,houseName,houseYear,houseFloors\n"); + + for (Flat flat : flats.values()) { + String line = String.format("%d,%s,%d,%d,%.2f,%d,%s,%s,%s,%s,%d,%d\n", + flat.getId(), + flat.getName(), + flat.getCoordinates().getX(), + flat.getCoordinates().getY(), + flat.getArea(), + flat.getNumberOfRooms(), + flat.getFurnish(), + flat.getView() != null ? flat.getView() : "", + flat.getTransport(), + flat.getHouse() != null ? flat.getHouse().getName() : "", + flat.getHouse() != null ? flat.getHouse().getYear() : 0, + flat.getHouse() != null ? flat.getHouse().getNumberOfFloors() : 0); + writer.write(line); + } + + return "Collection has been saved to the file successfully."; + } catch (IOException e) { + e.printStackTrace(); + return "An error occurred while saving the collection to file."; + } + } +} diff --git a/app/src/main/java/itmo/lab5/cli/commands/ShowCommand.java b/app/src/main/java/itmo/lab5/cli/commands/ShowCommand.java index 3b92e99..53b6f79 100644 --- a/app/src/main/java/itmo/lab5/cli/commands/ShowCommand.java +++ b/app/src/main/java/itmo/lab5/cli/commands/ShowCommand.java @@ -14,7 +14,7 @@ public class ShowCommand implements Command { try { collection = (HashMap) context.get("collection"); } catch (ClassCastException e) { - System.out.println("Can't parse collection!"); + return "Can't parse collection!"; } if (collection.isEmpty() || collection.size() == 0) {