diff --git a/app/src/main/java/itmo/lab5/App.java b/app/src/main/java/itmo/lab5/App.java index 5d93203..4fe4d77 100644 --- a/app/src/main/java/itmo/lab5/App.java +++ b/app/src/main/java/itmo/lab5/App.java @@ -5,14 +5,15 @@ import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.HashMap; import java.util.Scanner; import java.util.logging.*; import itmo.lab5.cli.CommandBuilder; +import itmo.lab5.cli.CommandInvoker; import itmo.lab5.cli.CommandContext; import itmo.lab5.cli.CommandRegistry; -import itmo.lab5.interfaces.Command; import itmo.lab5.cli.commands.*; import itmo.lab5.models.Flat; import itmo.lab5.parser.Reader; @@ -38,6 +39,12 @@ public class App { .register("insert", new InsertCommand()) .register("update", new UpdateCommand()) .register("save", new SaveCommand()) + .register("execute_script", new ExecuteCommand()) + .register("print_field_ascending_number_of_rooms", new FieldCommand()) + .register("filter_less_than_view", new FilterCommand("less")) + .register("filter_greater_than_view", new FilterCommand("greater")) + .register("replace_if_lower", new ReplaceCommand("lower")) + .register("replace_if_greater", new ReplaceCommand("greater")) .build(); try { @@ -53,29 +60,23 @@ public class App { context.set("history", history); context.set("path", dataFilePath.toString()); - var scanner = new Scanner(System.in); + CommandInvoker invoker = new CommandInvoker(registry, context, history); + context.set("commandInvoker", invoker); + var scanner = new Scanner(System.in); while (true) { System.out.print("> "); - String input = scanner.nextLine().trim(); if (input.isEmpty()) continue; String[] args = input.split(" "); String commandName = args[0]; - Command command = registry.getByName(commandName); + String[] commandArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]; - if (command != null) { - history.add(commandName); - var localArgs = args.length > 1 ? java.util.Arrays.copyOfRange(args, 1, args.length) : new String[0]; - var response = command.execute(localArgs, context); - System.out.println(response); - } else { - System.out.println("Unknown command: " + commandName); - } + String response = invoker.executeCommand(commandName, commandArgs); + System.out.println(response); } - } public static Path getDataFileFromEnv(String envVariable) throws IOException { diff --git a/app/src/main/java/itmo/lab5/cli/CommandInvoker.java b/app/src/main/java/itmo/lab5/cli/CommandInvoker.java index 1a9b5bb..c33fa57 100644 --- a/app/src/main/java/itmo/lab5/cli/CommandInvoker.java +++ b/app/src/main/java/itmo/lab5/cli/CommandInvoker.java @@ -3,7 +3,7 @@ package itmo.lab5.cli; import itmo.lab5.cli.helpers.History; import itmo.lab5.interfaces.*; -class CommandInvoker { +public class CommandInvoker { private final CommandRegistry registry; private final CommandContext context; private final History history; diff --git a/app/src/main/java/itmo/lab5/cli/commands/ExecuteCommand.java b/app/src/main/java/itmo/lab5/cli/commands/ExecuteCommand.java new file mode 100644 index 0000000..aa2eda7 --- /dev/null +++ b/app/src/main/java/itmo/lab5/cli/commands/ExecuteCommand.java @@ -0,0 +1,61 @@ +package itmo.lab5.cli.commands; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; +import java.util.Set; +import java.util.HashSet; + +import itmo.lab5.cli.CommandInvoker; +import itmo.lab5.cli.CommandContext; +import itmo.lab5.interfaces.*; + +public class ExecuteCommand implements Command { + private static final Set executingScripts = new HashSet(); + + @Override + public String execute(String args[], CommandContext context) { + if (args.length < 1) { + return "Usage: execute_script "; + } + + String fileName = args[0]; + File scriptFile = new File(fileName); + + if (executingScripts.contains(scriptFile.getAbsolutePath())) { + return "Error: Recursive script execution detected for file: " + fileName; + } + + executingScripts.add(scriptFile.getAbsolutePath()); + + try (Scanner fileScanner = new Scanner(scriptFile)) { + CommandInvoker commandInvoker = (CommandInvoker) context.get("commandInvoker"); + StringBuilder output = new StringBuilder(); + + while (fileScanner.hasNextLine()) { + String line = fileScanner.nextLine().trim(); + if (line.isEmpty() || line.startsWith("#")) { + continue; + } + + try { + String[] parts = line.split(" ", 2); + String commandName = parts[0]; + String[] commandArgs = parts.length > 1 ? parts[1].split(" ") : new String[0]; + + String result = commandInvoker.executeCommand(commandName, commandArgs); + output.append("> ").append(line).append("\n").append(result).append("\n"); + } catch (Exception e) { + output.append("Error executing command '").append(line).append("': ") + .append(e.getMessage()).append("\n"); + } + } + + return output.toString(); + } catch (FileNotFoundException e) { + return "Error: Script file not found: " + fileName; + } finally { + executingScripts.remove(scriptFile.getAbsolutePath()); + } + } +} diff --git a/app/src/main/java/itmo/lab5/cli/commands/FieldCommand.java b/app/src/main/java/itmo/lab5/cli/commands/FieldCommand.java new file mode 100644 index 0000000..24133d9 --- /dev/null +++ b/app/src/main/java/itmo/lab5/cli/commands/FieldCommand.java @@ -0,0 +1,36 @@ +package itmo.lab5.cli.commands; + +import itmo.lab5.cli.CommandContext; +import itmo.lab5.interfaces.Command; +import itmo.lab5.models.Flat; + +import java.util.*; +import java.util.stream.Collectors; + +public class FieldCommand implements Command { + @Override + public String execute(String args[], CommandContext context) { + var collection = new HashMap(); + + try { + collection = (HashMap) context.get("collection"); + } catch (ClassCastException e) { + return "Can't parse collection!"; + } + + if (collection.isEmpty() || collection.size() == 0) { + return "Nothing to show!"; + } + + List> sortedEntries = collection.entrySet().stream() + .sorted(Comparator.comparingInt(entry -> entry.getValue().getNumberOfRooms())) + .collect(Collectors.toList()); + + sortedEntries.forEach(entry -> { + System.out.println("Key: " + entry.getKey() + + ", Rooms: " + entry.getValue().getNumberOfRooms()); + }); + + return ""; + } +} diff --git a/app/src/main/java/itmo/lab5/cli/commands/FilterCommand.java b/app/src/main/java/itmo/lab5/cli/commands/FilterCommand.java new file mode 100644 index 0000000..92c902b --- /dev/null +++ b/app/src/main/java/itmo/lab5/cli/commands/FilterCommand.java @@ -0,0 +1,57 @@ +package itmo.lab5.cli.commands; + +import itmo.lab5.interfaces.*; +import itmo.lab5.cli.*; +import itmo.lab5.models.*; + +import java.util.HashMap; +import java.util.stream.Collectors; +import java.util.*; + +public class FilterCommand implements Command { + private String classificator; + + @Override + public String execute(String args[], CommandContext context) { + if (args.length < 1) + return "There's no classificator provided!"; + + var collection = new HashMap(); + Integer threshold = null; + List result; + + try { + collection = (HashMap) context.get("collection"); + threshold = Integer.parseInt(args[0]); + } catch (ClassCastException e) { + return "Can't parse collection!"; + } + + if (collection.isEmpty() || collection.size() == 0 || threshold == null) { + return "Nothing to show!"; + } + + final int finalThreshold = threshold; + if (classificator == "less") { + result = collection.values().stream() + .filter(flat -> flat.getView() != null && flat.getView().ordinal() < finalThreshold) + .sorted(Comparator.comparingInt(flat -> flat.getView().ordinal())) + .collect(Collectors.toList()); + } else { + result = collection.values().stream() + .filter(flat -> flat.getView() != null && flat.getView().ordinal() > finalThreshold) + .sorted(Comparator.comparingInt(flat -> flat.getView().ordinal())) + .collect(Collectors.toList()); + } + + result.forEach(entry -> { + System.out.println(entry); + }); + + return ""; + } + + public FilterCommand(String classificator) { + this.classificator = classificator; + } +} diff --git a/app/src/main/java/itmo/lab5/cli/commands/ReplaceCommand.java b/app/src/main/java/itmo/lab5/cli/commands/ReplaceCommand.java new file mode 100644 index 0000000..be87afc --- /dev/null +++ b/app/src/main/java/itmo/lab5/cli/commands/ReplaceCommand.java @@ -0,0 +1,51 @@ +package itmo.lab5.cli.commands; + +import itmo.lab5.cli.CommandContext; +import itmo.lab5.interfaces.*; +import itmo.lab5.models.Flat; + +import java.util.HashMap; + +public class ReplaceCommand implements Command { + private String classificator; + + public ReplaceCommand(String classificator) { + this.classificator = classificator; + } + + @Override + public String execute(String args[], CommandContext context) { + var collection = new HashMap(); + int idToUpdate; + + HashMap params = new HashMap<>(); + + for (String arg : args) { + String[] parts = arg.split("=", 2); + if (parts.length == 2) + params.put(parts[0], parts[1]); + } + + if (args.length < 1) + return "Can't get value without id!"; + + try { + collection = (HashMap) context.get("collection"); + } catch (ClassCastException e) { + return "Can't parse collection!"; + } + + try { + idToUpdate = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + return "Can't parse provided id!"; + } + + if (collection.isEmpty() || collection.size() == 0) + return "Nothing to show!"; + + var currentFlat = collection.get(idToUpdate); + + return ""; + } +} diff --git a/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java b/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java index 00c65bd..881018d 100644 --- a/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java +++ b/app/src/main/java/itmo/lab5/cli/commands/SaveCommand.java @@ -9,6 +9,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.io.BufferedWriter; import java.util.HashMap; +import java.text.SimpleDateFormat; public class SaveCommand implements Command { @Override @@ -30,19 +31,28 @@ public class SaveCommand implements Command { } } + static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + 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", + String date = ""; + + try { + date = dateFormat.format(flat.getCreationDate()).toString(); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + String line = String.format("%d,%s,%d,%d,%s,%.2f,%d,%s,%s,%s,%s,%d,%d\n", flat.getId(), flat.getName(), flat.getCoordinates().getX(), flat.getCoordinates().getY(), + date, flat.getArea(), flat.getNumberOfRooms(), flat.getFurnish(), diff --git a/app/src/main/java/itmo/lab5/cli/commands/UpdateCommand.java b/app/src/main/java/itmo/lab5/cli/commands/UpdateCommand.java index c28ac2a..b4346c8 100644 --- a/app/src/main/java/itmo/lab5/cli/commands/UpdateCommand.java +++ b/app/src/main/java/itmo/lab5/cli/commands/UpdateCommand.java @@ -33,9 +33,8 @@ public class UpdateCommand implements Command { return "There's an error while trying to parse collection"; } - if (!collection.containsKey(idToUpdate)) { + if (!collection.containsKey(idToUpdate)) return "No flat with ID: " + idToUpdate; - } Flat oldFlat = collection.get(idToUpdate);