diff --git a/src/main/java/com/javarush/ivanov/ConsoleRunner.java b/src/main/java/com/javarush/ivanov/ConsoleRunner.java deleted file mode 100644 index e40fff2..0000000 --- a/src/main/java/com/javarush/ivanov/ConsoleRunner.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.javarush.ivanov; - -public class ConsoleRunner { - public static void main(String[] args) { - // Create package with your lastname in com.javarush - // and add your solution like this - System.out.println("у вас будет такой же пакет, но со своим решением"); - } -} \ No newline at end of file diff --git a/src/main/java/com/javarush/khmelov/ConsoleRunner.java b/src/main/java/com/javarush/khmelov/ConsoleRunner.java deleted file mode 100644 index b8eeab6..0000000 --- a/src/main/java/com/javarush/khmelov/ConsoleRunner.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.javarush.khmelov; - -import com.javarush.khmelov.controller.MainController; -import com.javarush.khmelov.view.console.ConsoleApp; -import com.javarush.khmelov.view.console.Menu; - -import java.util.Scanner; - -public class ConsoleRunner { - - public static void main(String[] args) { - //build console app - Scanner input = new Scanner(System.in); - Menu menu = new Menu(input); - MainController mainController = new MainController(); - ConsoleApp application = new ConsoleApp(mainController, menu); - //run console app - application.run(args); - } - - -} - diff --git a/src/main/java/com/javarush/khmelov/PicocliRunner.java b/src/main/java/com/javarush/khmelov/PicocliRunner.java deleted file mode 100644 index 6fb0c8f..0000000 --- a/src/main/java/com/javarush/khmelov/PicocliRunner.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.javarush.khmelov; - -import picocli.CommandLine; -import com.javarush.khmelov.controller.MainController; -import com.javarush.khmelov.view.picocli.Picocli; -import com.javarush.khmelov.view.picocli.PicocliApp; - -public class PicocliRunner { - public static void main(String[] args) { - //app build - MainController mainController = new MainController(); - PicocliApp application = new PicocliApp(mainController); - - //run picocli - Picocli command = new Picocli(application); - CommandLine commandLine = new CommandLine(command); - int exitCode = commandLine.execute(args); - - //return result - System.exit(exitCode); - } -} diff --git a/src/main/java/com/javarush/khmelov/SwingRunner.java b/src/main/java/com/javarush/khmelov/SwingRunner.java deleted file mode 100644 index ec5aad3..0000000 --- a/src/main/java/com/javarush/khmelov/SwingRunner.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.javarush.khmelov; - -import com.javarush.khmelov.controller.MainController; -import com.javarush.khmelov.view.swing.MainForm; - -public class SwingRunner { - public static void main(String[] args) { - //build swing app - MainController controller = new MainController(); - MainForm mainForm = new MainForm(controller); - - //run swing app - mainForm.initialization(); - } -} diff --git a/src/main/java/com/javarush/khmelov/command/AbstractAction.java b/src/main/java/com/javarush/khmelov/command/AbstractAction.java deleted file mode 100644 index a02ea2e..0000000 --- a/src/main/java/com/javarush/khmelov/command/AbstractAction.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.constant.Alphabet; -import com.javarush.khmelov.constant.Const; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.entity.ResultCode; -import com.javarush.khmelov.exception.AppException; -import com.javarush.khmelov.util.PathBuilder; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -public abstract class AbstractAction implements Action{ - - //common methods for actions: Encode Decode Bruteforce - public Result copyWithKey(String sourceTextFile, String targetTextFile, int key) { - Path source = PathBuilder.get(sourceTextFile); - Path target = PathBuilder.get(targetTextFile); - try ( - BufferedReader reader = Files.newBufferedReader(source); - BufferedWriter writer = Files.newBufferedWriter(target) - ) { - int value; - int length = Alphabet.chars.length; - while ((value = reader.read()) > -1) { - char character = (char) value; - character = Character.toLowerCase(character); - if (Alphabet.index.containsKey(character)) { - Integer index = Alphabet.index.get(character); - index = (index + key + Math.abs(key) * length) % length; - writer.write(Alphabet.chars[index]); - } else if (character == '\n') { - writer.write(character); - } - } - } catch (IOException e) { - throw new AppException(Const.INCORRECT_FILE + e.getMessage(), e); - } - return new Result(ResultCode.OK, targetTextFile); - } -} diff --git a/src/main/java/com/javarush/khmelov/command/Action.java b/src/main/java/com/javarush/khmelov/command/Action.java deleted file mode 100644 index b72bc84..0000000 --- a/src/main/java/com/javarush/khmelov/command/Action.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.entity.Result; - -public interface Action { - - Result execute(String[] parameters); - - -} diff --git a/src/main/java/com/javarush/khmelov/command/Analyze.java b/src/main/java/com/javarush/khmelov/command/Analyze.java deleted file mode 100644 index 9de6883..0000000 --- a/src/main/java/com/javarush/khmelov/command/Analyze.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.constant.Alphabet; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.entity.ResultCode; -import com.javarush.khmelov.exception.AppException; -import com.javarush.khmelov.util.PathBuilder; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; - -public class Analyze extends AbstractAction { - @Override - public Result execute(String[] parameters) { - String encryptedFilename = parameters[0]; - String dictionaryFilename = parameters[1]; - String analyzedFilename = parameters[2]; - - List dictChar = getSortedChars(dictionaryFilename); - List sourceChar = getSortedChars(encryptedFilename); - - Path source = PathBuilder.get(encryptedFilename); - Path target = PathBuilder.get(analyzedFilename); - try ( - BufferedReader reader = Files.newBufferedReader(source); - BufferedWriter writer = Files.newBufferedWriter(target) - ) { - int value; - while ((value = reader.read()) > -1) { - char character = (char) value; - int index = sourceChar.indexOf(character); - Character characterDecrypted = dictChar.get(index); - writer.write( - characterDecrypted != null - ? characterDecrypted - : character); - } - } catch (IOException e) { - throw new AppException(e.getMessage(), e); - } - return new Result(ResultCode.OK, analyzedFilename); - } - - private List getSortedChars(String encryptedFile) { - Map map = createStartMap(); - Path path = PathBuilder.get(encryptedFile); - try (BufferedReader reader = Files.newBufferedReader(path)) { - int value; - while ((value = reader.read()) > -1) { - char character = (char) value; - character = Character.toLowerCase(character); - if (map.containsKey(character)) { - Integer i = map.get(character); - map.put(character, ++i); - } - } - } catch (IOException e) { - throw new AppException(e.getMessage(), e); - } - - return map.entrySet() - .stream() - .sorted(Comparator.comparingInt(Map.Entry::getValue)) - .map(Map.Entry::getKey) - .toList(); - } - - private Map createStartMap() { - return Alphabet.index.keySet() - .stream() - .collect(Collectors.toMap( - character -> character, - character -> 0, (a, b) -> b, - LinkedHashMap::new - )); - } - -} diff --git a/src/main/java/com/javarush/khmelov/command/BruteForce.java b/src/main/java/com/javarush/khmelov/command/BruteForce.java deleted file mode 100644 index f990652..0000000 --- a/src/main/java/com/javarush/khmelov/command/BruteForce.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.constant.Alphabet; -import com.javarush.khmelov.constant.Const; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.exception.AppException; -import com.javarush.khmelov.util.PathBuilder; - -import java.io.BufferedReader; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -public class BruteForce extends AbstractAction { - - @Override - public Result execute(String[] parameters) { - String encryptedFilename = parameters[0]; - String decryptedFilename = parameters[1]; - int bestKey = 0; - int bestSpaceCount = 0; - char space = ' '; - for (int key = 0; key < Alphabet.chars.length; key++) { - int spaceCount = countCharInFileWithKey(encryptedFilename, key, space); - if (spaceCount > bestSpaceCount) { - bestSpaceCount = spaceCount; - bestKey = key; - } - } - return copyWithKey(encryptedFilename, decryptedFilename, bestKey); - } - - private int countCharInFileWithKey(String encryptedFilename, int key, char fixChar) { - int spaceCount = 0; - Path path = PathBuilder.get(encryptedFilename); - try (BufferedReader reader = Files.newBufferedReader(path)) { - int value; - while ((value = reader.read()) > -1) { - char character = (char) value; - if (Alphabet.index.containsKey(character)) { - int index = Alphabet.index.get(character); - index = (index + key + Alphabet.chars.length) % Alphabet.chars.length; - if (Alphabet.chars[index] == fixChar) { - spaceCount++; - } - } - } - } catch (IOException e) { - throw new AppException(Const.INCORRECT_FILE + encryptedFilename, e); - } - return spaceCount; - } -} diff --git a/src/main/java/com/javarush/khmelov/command/Decode.java b/src/main/java/com/javarush/khmelov/command/Decode.java deleted file mode 100644 index 10e5f9c..0000000 --- a/src/main/java/com/javarush/khmelov/command/Decode.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.entity.Result; - -public class Decode extends AbstractAction { - @Override - public Result execute(String[] parameters) { - String encryptedFilename = parameters[0]; - String decryptedFilename = parameters[1]; - int key = Integer.parseInt(parameters[2]); - return copyWithKey(encryptedFilename, decryptedFilename, -1 * key); - } - -} diff --git a/src/main/java/com/javarush/khmelov/command/Encode.java b/src/main/java/com/javarush/khmelov/command/Encode.java deleted file mode 100644 index de09ab0..0000000 --- a/src/main/java/com/javarush/khmelov/command/Encode.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.entity.Result; - -public class Encode extends AbstractAction { - @Override - public Result execute(String[] parameters) { - String sourceTextFile = parameters[0]; - String encryptedFile = parameters[1]; - int key = Integer.parseInt(parameters[2]); - return copyWithKey(sourceTextFile, encryptedFile, key); - } -} diff --git a/src/main/java/com/javarush/khmelov/command/Exit.java b/src/main/java/com/javarush/khmelov/command/Exit.java deleted file mode 100644 index 0a3072f..0000000 --- a/src/main/java/com/javarush/khmelov/command/Exit.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.javarush.khmelov.command; - -import com.javarush.khmelov.constant.Const; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.entity.ResultCode; - -public class Exit extends AbstractAction { - - @Override - public Result execute(String[] parameters) { - return new Result(ResultCode.OK, Const.APPLICATION_CLOSED); - } -} diff --git a/src/main/java/com/javarush/khmelov/constant/Alphabet.java b/src/main/java/com/javarush/khmelov/constant/Alphabet.java deleted file mode 100644 index fa1c66b..0000000 --- a/src/main/java/com/javarush/khmelov/constant/Alphabet.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.javarush.khmelov.constant; - -import java.util.HashMap; -import java.util.Map; - -public class Alphabet { - - private Alphabet() { - } - - private static final String rus = "ЙЦУКЕНГШЩЗХЪЭЖДЛОРПАВЫФЯЧСМИТЬБЮ"; - private static final String symbols = "\n☮.,”’:-!? "; - - public static final char[] chars = (rus.toLowerCase() + symbols).toCharArray(); - - public final static Map index = new HashMap<>(); - - static { - for (int i = 0; i < chars.length; i++) { - index.put(chars[i], i); - } - } -} diff --git a/src/main/java/com/javarush/khmelov/constant/Const.java b/src/main/java/com/javarush/khmelov/constant/Const.java deleted file mode 100644 index 88f9448..0000000 --- a/src/main/java/com/javarush/khmelov/constant/Const.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.javarush.khmelov.constant; - -import java.io.File; - -public interface Const { - String ENCODE = "encode"; - String DECODE = "decode"; - String BRUTEFORCE = "bruteforce"; - String ANALYZE = "analyze"; - - String TXT_FOLDER = System.getProperty("user.dir") + - File.separator + - "text" + - File.separator; - - String NOT_FOUND_ACTION_FORMAT = "not found action: %s"; - String INCORRECT_FILE = "Incorrect file: "; - String APPLICATION_CLOSED = "application closed"; -} \ No newline at end of file diff --git a/src/main/java/com/javarush/khmelov/controller/ActionContainer.java b/src/main/java/com/javarush/khmelov/controller/ActionContainer.java deleted file mode 100644 index 67aaf5d..0000000 --- a/src/main/java/com/javarush/khmelov/controller/ActionContainer.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.javarush.khmelov.controller; - -import com.javarush.khmelov.command.*; -import com.javarush.khmelov.constant.Const; -import com.javarush.khmelov.exception.AppException; - -@SuppressWarnings("unused") -public enum ActionContainer { - - ENCODE(new Encode()), - DECODE(new Decode()), - BRUTEFORCE(new BruteForce()), - ANALYZE(new Analyze()), - EXIT(new Exit()); - - private final Action action; - - ActionContainer(Action action) { - this.action = action; - } - - public static Action get(String actionName) { - try { - ActionContainer value = ActionContainer.valueOf(actionName.toUpperCase()); - return value.action; - } catch (IllegalArgumentException e) { - String message = String.format(Const.NOT_FOUND_ACTION_FORMAT, actionName); - throw new AppException(message, e); - } - } -} diff --git a/src/main/java/com/javarush/khmelov/controller/MainController.java b/src/main/java/com/javarush/khmelov/controller/MainController.java deleted file mode 100644 index 807ead5..0000000 --- a/src/main/java/com/javarush/khmelov/controller/MainController.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.javarush.khmelov.controller; - -import com.javarush.khmelov.command.Action; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.entity.ResultCode; -import com.javarush.khmelov.exception.AppException; - -public class MainController { - - public Result doAction(String actionName, String[] parameters) { - Action action = ActionContainer.get(actionName); - try { - return action.execute(parameters); - } catch (NumberFormatException | AppException e) { - return new Result(ResultCode.ERROR, e.getMessage()); - } - } -} diff --git a/src/main/java/com/javarush/khmelov/entity/Result.java b/src/main/java/com/javarush/khmelov/entity/Result.java deleted file mode 100644 index c77764a..0000000 --- a/src/main/java/com/javarush/khmelov/entity/Result.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.javarush.khmelov.entity; - -public class Result { - public final ResultCode resultCode; - public final String message; - - public Result(ResultCode resultCode, String message) { - this.resultCode = resultCode; - this.message = message; - } - - @Override - public String toString() { - return "Result{" + - "resultCode=" + resultCode + - ", resultFile='" + message + '\'' + - '}'; - } -} diff --git a/src/main/java/com/javarush/khmelov/entity/ResultCode.java b/src/main/java/com/javarush/khmelov/entity/ResultCode.java deleted file mode 100644 index 6e37db8..0000000 --- a/src/main/java/com/javarush/khmelov/entity/ResultCode.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.javarush.khmelov.entity; - -public enum ResultCode { - OK, ERROR -} diff --git a/src/main/java/com/javarush/khmelov/exception/AppException.java b/src/main/java/com/javarush/khmelov/exception/AppException.java deleted file mode 100644 index 4f3d62d..0000000 --- a/src/main/java/com/javarush/khmelov/exception/AppException.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.javarush.khmelov.exception; - -public class AppException extends RuntimeException{ - - public AppException() { - } - - public AppException(String message, Throwable cause) { - super(message, cause); - } - - public AppException(Throwable cause) { - super(cause); - } - - public AppException(String message) { - super(message); - } -} diff --git a/src/main/java/com/javarush/khmelov/util/PathBuilder.java b/src/main/java/com/javarush/khmelov/util/PathBuilder.java deleted file mode 100644 index 4ecf056..0000000 --- a/src/main/java/com/javarush/khmelov/util/PathBuilder.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.javarush.khmelov.util; - -import com.javarush.khmelov.constant.Const; - -import java.nio.file.Path; - -public class PathBuilder { - - private PathBuilder() { - } - - public static Path get(String filename) { - Path path = Path.of(filename); - return path.isAbsolute() - ? path - : Path.of(Const.TXT_FOLDER + filename); - } -} - diff --git a/src/main/java/com/javarush/khmelov/view/console/ConsoleApp.java b/src/main/java/com/javarush/khmelov/view/console/ConsoleApp.java deleted file mode 100644 index ad6cac6..0000000 --- a/src/main/java/com/javarush/khmelov/view/console/ConsoleApp.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.javarush.khmelov.view.console; - -import com.javarush.khmelov.controller.MainController; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.entity.ResultCode; - -import java.util.Arrays; - -public class ConsoleApp { - - private final MainController mainController; - private final Menu menu; - - public ConsoleApp(MainController mainController, Menu menu) { - this.mainController = mainController; - this.menu = menu; - } - - public void run(String[] args) { - Result result; - do { - if (args.length == 0) { - args = menu.getArgs(); - } - result = getResult(args); - print(result); - args = new String[0]; - } while (result.resultCode == ResultCode.ERROR); - } - - - private Result getResult(String[] args) { - String action = args[0]; - String[] parameters = Arrays.copyOfRange(args, 1, args.length); - return mainController.doAction(action, parameters); - } - - private void print(Result result) { - String message = switch (result.resultCode) { - case OK -> String.format( - Messages.OK_FORMAT, result.message - ); - case ERROR -> String.format( - Messages.ERR_FORMAT, result.message - ); - }; - System.out.println(message); - } -} diff --git a/src/main/java/com/javarush/khmelov/view/console/Menu.java b/src/main/java/com/javarush/khmelov/view/console/Menu.java deleted file mode 100644 index 2bb538b..0000000 --- a/src/main/java/com/javarush/khmelov/view/console/Menu.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.javarush.khmelov.view.console; - -import java.util.Scanner; - -import static com.javarush.khmelov.view.console.Messages.*; - -public class Menu { - - private final Scanner scanner; - - public Menu(Scanner scanner) { - this.scanner = scanner; - } - - public String[] getArgs() { - int mode = getMode(scanner); - String[] args = new String[QUESTIONS[mode].length]; - args[0] = QUESTIONS[mode][0][0]; - for (int i = 1; i < args.length; i++) { - String quest = QUESTIONS[mode][i][0]; - System.out.println(quest); - String answer = scanner.nextLine(); - args[i] = "".equals(answer.trim()) ? QUESTIONS[mode][i][1] : answer; - } - return args; - } - - private static int getMode(Scanner scanner) { - int mode; - do { - System.out.println(MESSAGE_SELECT_MODE); - String input = scanner.nextLine(); - mode = switch (input) { - case "1" -> 0; - case "2" -> 1; - case "3" -> 2; - case "4" -> 3; - case "5" -> 4; - default -> { - System.out.println(INCORRECT_SELECTION); - yield -1; - } - }; - } while (mode < 0); - return mode; - } -} diff --git a/src/main/java/com/javarush/khmelov/view/console/Messages.java b/src/main/java/com/javarush/khmelov/view/console/Messages.java deleted file mode 100644 index c57de4c..0000000 --- a/src/main/java/com/javarush/khmelov/view/console/Messages.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.javarush.khmelov.view.console; - -import com.javarush.khmelov.constant.Const; - -interface Messages { - String[][][] QUESTIONS = new String[][][]{ - { - {Const.ENCODE}, - {"Enter source (full path OR only filename OR Enter for text.txt) :", "text.txt"}, - {"Enter destination (full path OR only filename OR Enter for encrypted.txt) :", "encrypted.txt"}, - {"Enter key (int number OR Enter for key=1) :", "1"}, - }, - { - {Const.DECODE}, - {"Enter source (full path OR only filename OR Enter for encrypted.txt) :", "encrypted.txt"}, - {"Enter destination (full path OR only filename OR Enter for decrypted.txt) :", "decrypted.txt"}, - {"Enter key (int number OR Enter for key=1) :", "1"}, - }, - { - {Const.BRUTEFORCE}, - {"Enter source (full path OR only filename OR Enter for encrypted.txt) :", "encrypted.txt"}, - {"Enter destination (full path OR only filename OR Enter for bruteforce.txt) :", "bruteforce.txt"}, - }, - { - {Const.ANALYZE}, - {"Enter source (full path OR only filename OR Enter for encrypted.txt) :", "encrypted.txt"}, - {"Enter dictionary (full path OR only filename OR Enter for dict.txt) :", "dict.txt"}, - {"Enter destination (full path OR only filename OR Enter for analyzed.txt) :", "analyzed.txt"}, - }, - { - {"Exit"}, - } - }; - - String ANSI_RESET = "\u001B[0m"; - String ANSI_BLUE = "\u001B[34m"; - String ANSI_CYAN = "\u001B[36m"; - String ANSI_PURPLE = "\u001B[35m"; - String ANSI_GREEN = "\u001B[32m"; - - String LINE = "-".repeat(20); - String MESSAGE_SELECT_MODE = LINE + - ANSI_BLUE + "\nPlease select mode:\n" + ANSI_CYAN + """ - 1. Encrypt - 2. Decrypt - 3. Brute force - 4. Analyze - 5. Exit - """ + ANSI_RESET + LINE; - - String INCORRECT_SELECTION = "Incorrect selection"; - - String OK_FORMAT = ANSI_GREEN + """ - Operation complete - Result: %s - """ + ANSI_RESET; - - String ERR_FORMAT = ANSI_PURPLE + """ - ERROR - Message: %s - """ + ANSI_RESET; - - -} diff --git a/src/main/java/com/javarush/khmelov/view/picocli/Messages.java b/src/main/java/com/javarush/khmelov/view/picocli/Messages.java deleted file mode 100644 index aca032d..0000000 --- a/src/main/java/com/javarush/khmelov/view/picocli/Messages.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.javarush.khmelov.view.picocli; - -interface Messages { - - String ENCODE_HELP = "Encrypt from file to file using key"; - String DECODE_HELP = "Decrypt from file to file using key"; - String BRUTEFORCE_HELP = "Decrypt from file to file using brute force"; - String ANALYZE_HELP = "Decrypt from file to file using statistical analysis"; - - String SOURCE_FILE = ""; - String DICT_FILE = ""; - String DEST_FILE = ""; - String KEY = ""; - - String SOURCE_HELP = "source file with text to encrypt"; - String ENCRYPTED_SOURCE_HELP = "source file with encrypted text"; - String DICT_HELP = "dictionary file with sample test"; - String DEST_FILE_HELP = "dest file which should have decrypted text"; - String DEST_ENCRYPTED_FILE_HELP = "dest file which should have encrypted text"; - String KEY_HELP = "key for encryption"; - - String SPECIFY_A_SUBCOMMAND = "Specify a subcommand"; - String APP_NAME = "PicocliRunner"; - String APP_DESCRIPTION = "Example: PicocliRunner command parameters..."; -} diff --git a/src/main/java/com/javarush/khmelov/view/picocli/Picocli.java b/src/main/java/com/javarush/khmelov/view/picocli/Picocli.java deleted file mode 100644 index 9f912b9..0000000 --- a/src/main/java/com/javarush/khmelov/view/picocli/Picocli.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.javarush.khmelov.view.picocli; - -import picocli.CommandLine; -import picocli.CommandLine.Command; -import picocli.CommandLine.Model.CommandSpec; -import picocli.CommandLine.ParameterException; -import picocli.CommandLine.Parameters; -import picocli.CommandLine.Spec; -import com.javarush.khmelov.constant.Const; -import com.javarush.khmelov.entity.Result; - -import static com.javarush.khmelov.view.picocli.Messages.*; - -@SuppressWarnings("unused") -@Command(name = APP_NAME, subcommands = {CommandLine.HelpCommand.class}, - description = APP_DESCRIPTION) -public class Picocli implements Runnable { - - private final PicocliApp application; - - public Picocli(PicocliApp application) { - this.application = application; - } - - @Spec - CommandSpec spec; - - @Command(name = Const.ENCODE, description = ENCODE_HELP) - void encode( - @Parameters(paramLabel = SOURCE_FILE, description = SOURCE_HELP) String src, - @Parameters(paramLabel = DEST_FILE, description = DEST_ENCRYPTED_FILE_HELP) String dest, - @Parameters(paramLabel = KEY, description = KEY_HELP) String key) { - String[] args = {Const.ENCODE, src, dest, key}; - Result result = application.run(args); - System.out.println(result); - } - - @Command(name = Const.DECODE, description = DECODE_HELP) - void decode( - @Parameters(paramLabel = SOURCE_FILE, description = ENCRYPTED_SOURCE_HELP) String src, - @Parameters(paramLabel = DEST_FILE, description = DEST_FILE_HELP) String dest, - @Parameters(paramLabel = KEY, description = KEY_HELP) String key) { - String[] args = {Const.DECODE, src, dest, key}; - Result result = application.run(args); - System.out.println(result); - } - - @Command(name = Const.BRUTEFORCE, description = BRUTEFORCE_HELP) - void bruteForce( - @Parameters(paramLabel = SOURCE_FILE, description = ENCRYPTED_SOURCE_HELP) String src, - @Parameters(paramLabel = DEST_FILE, description = DEST_FILE_HELP) String dest) { - String[] args = {Const.BRUTEFORCE, src, dest}; - Result result = application.run(args); - System.out.println(result); - } - - @Command(name = Const.ANALYZE, description = ANALYZE_HELP) - void analyze( - @Parameters(paramLabel = SOURCE_FILE, description = ENCRYPTED_SOURCE_HELP) String src, - @Parameters(paramLabel = DICT_FILE, description = DICT_HELP) String dict, - @Parameters(paramLabel = DEST_FILE, description = DEST_FILE_HELP) String dest) { - String[] args = {Const.ANALYZE, src, dict, dest}; - Result result = application.run(args); - System.out.println(result); - } - - - @Override - public void run() { - throw new ParameterException(spec.commandLine(), SPECIFY_A_SUBCOMMAND); - } -} - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/java/com/javarush/khmelov/view/picocli/PicocliApp.java b/src/main/java/com/javarush/khmelov/view/picocli/PicocliApp.java deleted file mode 100644 index dcf3f3d..0000000 --- a/src/main/java/com/javarush/khmelov/view/picocli/PicocliApp.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.javarush.khmelov.view.picocli; - -import com.javarush.khmelov.controller.MainController; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.exception.AppException; - -import java.util.Arrays; - -public class PicocliApp { - - private final MainController mainController; - - public PicocliApp(MainController mainController) { - this.mainController = mainController; - } - - public Result run(String[] args) { - if (args.length > 0) { - String action = args[0]; - String[] parameters = Arrays.copyOfRange(args, 1, args.length); - return mainController.doAction(action, parameters); - } else - throw new AppException("no args"); - } -} diff --git a/src/main/java/com/javarush/khmelov/view/swing/MainForm.form b/src/main/java/com/javarush/khmelov/view/swing/MainForm.form deleted file mode 100644 index cd591e5..0000000 --- a/src/main/java/com/javarush/khmelov/view/swing/MainForm.form +++ /dev/null @@ -1,399 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/java/com/javarush/khmelov/view/swing/MainForm.java b/src/main/java/com/javarush/khmelov/view/swing/MainForm.java deleted file mode 100644 index fa34d64..0000000 --- a/src/main/java/com/javarush/khmelov/view/swing/MainForm.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.javarush.khmelov.view.swing; - -import com.javarush.khmelov.constant.Const; -import com.javarush.khmelov.controller.MainController; -import com.javarush.khmelov.entity.Result; -import com.javarush.khmelov.entity.ResultCode; -import com.javarush.khmelov.util.PathBuilder; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.nio.file.Files; -import java.util.Objects; - -@SuppressWarnings("unused") -public class MainForm extends JFrame { - - private static final int PERCENT_SCREEN = 60; - public static final int MAX_PERCENT_SCREEN = 100; - public static final String OK_MESSAGE = "OK"; - - private final MainController controller; - - private JPanel panel; - private JPanel top; - private JPanel left; - private JPanel right; - private JPanel bottom; - private JPanel content; - private JTextArea textArea; - private JButton setText; - private JButton setEncrypted; - private JTextField text; - private JTextField encrypted; - private JButton setDecrypted; - private JButton setBruteforce; - private JButton setAnalyzed; - private JTextField decrypted; - private JTextField bruteforce; - private JTextField analyzed; - private JButton runEncode; - private JButton runDecode; - private JButton runBruteforce; - private JButton runAnalyze; - private JButton loadText; - private JButton loadEncrypted; - private JButton loadDecrypted; - private JButton loadBruteforce; - private JButton loadAnalyzed; - private JSlider keySlider; - private JButton swap; - private JSpinner key; - private JButton loadDict; - private JTextField dict; - private JButton setDict; - private JTextField ch1; - private JTextField ch2; - private JLabel currentFilename; - - public MainForm(MainController controller) { - this.controller = controller; - } - - static { - setLookAndFeel("Nimbus"); - } - - @SuppressWarnings("SameParameterValue") - private static void setLookAndFeel(String nameLookAndFeel) { - try { - for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { - if (nameLookAndFeel.equals(info.getName())) { - UIManager.setLookAndFeel(info.getClassName()); - break; - } - } - } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { - LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); - System.out.println(lookAndFeel); - } - } - - public void initialization() { - setIcon(); - initView(); - - initOpenFileDialogs(); - initLoadButtons(); - initCommandListeners(); - initKeyListeners(); - initCharacterSwapListeners(); - initCharacterInputListener(); - } - - private void initView() { - this.add(panel); - setVisible(true); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setStartPosition(); - setDefaultValues(text, encrypted, decrypted, bruteforce, dict, analyzed); - } - - private void setIcon() { - URL png = getClass().getResource("/icon.png"); - Image image = Toolkit.getDefaultToolkit().getImage(png); - this.setIconImage(image); - } - - - private void initOpenFileDialogs() { - addDialog(setText, text); - addDialog(setEncrypted, encrypted); - addDialog(setDecrypted, decrypted); - addDialog(setBruteforce, bruteforce); - addDialog(setDict, dict); - addDialog(setAnalyzed, analyzed); - } - - private void initLoadButtons() { - setLoad(loadText, text); - setLoad(loadEncrypted, encrypted); - setLoad(loadDecrypted, decrypted); - setLoad(loadBruteforce, bruteforce); - setLoad(loadDict, dict); - setLoad(loadAnalyzed, analyzed); - } - - private void initCommandListeners() { - runEncode.addActionListener(e -> run(Const.ENCODE, - text.getText(), encrypted.getText(), key.getValue().toString())); - runDecode.addActionListener(e -> run(Const.DECODE, - encrypted.getText(), decrypted.getText(), key.getValue().toString())); - runBruteforce.addActionListener(e -> run(Const.BRUTEFORCE, - encrypted.getText(), bruteforce.getText())); - runAnalyze.addActionListener(e -> run(Const.ANALYZE, - encrypted.getText(), dict.getText(), analyzed.getText())); - } - - private void initKeyListeners() { - - int startKey = 1; - key.setValue(startKey); - keySlider.setValue(startKey); - - keySlider.addChangeListener(e -> { - int value = keySlider.getValue(); - key.setValue(value); - }); - - key.addChangeListener(e -> { - int value = Integer.parseInt(key.getValue().toString()); - keySlider.setValue(value); - }); - - } - - private void initCharacterSwapListeners() { - swap.addActionListener(e -> { - char ch1 = this.ch1.getText().charAt(0); - char ch2 = this.ch2.getText().charAt(0); - - String text = textArea.getText(); - text = text.replace(ch1, '~'); - text = text.replace(ch2, ch1); - text = text.replace('~', ch2); - textArea.setText(text); - textArea.setCaretPosition(0); - }); - } - - private void initCharacterInputListener() { - ch1.addKeyListener(clearField()); - ch2.addKeyListener(clearField()); - } - - private void setLoad(JButton loadButton, JTextField textField) { - loadButton.addActionListener(e -> loadText(textField.getText())); - } - - private void run(String command, String... parameters) { - Result result = controller.doAction(command, parameters); - if (result.resultCode == ResultCode.OK) { - loadText(result.message); - } else { - System.out.println(result); - } - } - - private void loadText(String filename) { - try { - String string = Files.readString(PathBuilder.get(filename)); - textArea.setText(string); - textArea.setCaretPosition(0); - currentFilename.setText("View file: " + filename); - } catch (IOException ex) { - JOptionPane.showMessageDialog(this, - "Can't load file:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); - } - } - - private void setDefaultValues(JTextField... filenames) { - for (JTextField filename : filenames) { - String name = filename.getText(); - filename.setText(PathBuilder.get(name).toString()); - } - } - - private void setStartPosition() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - Dimension screenSize = toolkit.getScreenSize(); - int width = screenSize.width * PERCENT_SCREEN / MAX_PERCENT_SCREEN; - int height = screenSize.height * PERCENT_SCREEN / MAX_PERCENT_SCREEN; - int offsetX = (screenSize.width - width) / 2; - int offsetY = (screenSize.height - height) / 2; - setBounds(offsetX, offsetY, width, height); - } - - private void addDialog(JButton changeButton, JTextField jTextField) { - changeButton.addActionListener(e -> { - File file = new File(jTextField.getText()); - JFileChooser jFileChooser = new JFileChooser(file.getParent()); - jFileChooser.showDialog(this, OK_MESSAGE); - File selectedFile = jFileChooser.getSelectedFile(); - if (Objects.nonNull(selectedFile)) { - jTextField.setText(selectedFile.toString()); - } - }); - - } - - private KeyAdapter clearField() { - return new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - ((JTextField) e.getSource()).setText(""); - } - }; - } - - -} diff --git a/src/main/resources/Alphabet.java b/src/main/resources/Alphabet.java new file mode 100644 index 0000000..3a2e0de --- /dev/null +++ b/src/main/resources/Alphabet.java @@ -0,0 +1,9 @@ +package ru.javarush.lim.cryptoanalizer.util.alphabet; + +import java.util.Map; + +@FunctionalInterface +public interface Alphabet extends Parser, Mapper { + + Map build(String symbols); +} \ No newline at end of file diff --git a/src/main/resources/AlphabetConfig.java b/src/main/resources/AlphabetConfig.java new file mode 100644 index 0000000..1efa671 --- /dev/null +++ b/src/main/resources/AlphabetConfig.java @@ -0,0 +1,7 @@ +package ru.javarush.lim.cryptoanalizer.util.alphabet; + +public class AlphabetConfig { + public static final String RUSSIAN = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" + + "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" + + ".,«»:!?\"' "; +} diff --git a/src/main/resources/AlphabetData.java b/src/main/resources/AlphabetData.java new file mode 100644 index 0000000..d6eb155 --- /dev/null +++ b/src/main/resources/AlphabetData.java @@ -0,0 +1,18 @@ +package ru.javarush.lim.cryptoanalizer.util.alphabet; + +import java.util.LinkedHashMap; +import java.util.Map; + +public record AlphabetData(Map direct, Map reverse, String symbols) { + + public static AlphabetData from(String symbols, Alphabet alphabet) { + Map direct = alphabet.build(symbols); + Map reverse = new LinkedHashMap<>(); + direct.forEach((ch, idx) -> reverse.put(idx, ch)); + return new AlphabetData(direct, reverse, symbols); + } + + public String symbolsAsString() { + return symbols; + } +} diff --git a/src/main/resources/CaesarFileCipher.java b/src/main/resources/CaesarFileCipher.java new file mode 100644 index 0000000..44046a8 --- /dev/null +++ b/src/main/resources/CaesarFileCipher.java @@ -0,0 +1,68 @@ +package ru.javarush.lim.cryptoanalizer.util.cipher; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Function; + +public class CaesarFileCipher implements Cipher, Process, ExtendedAcceptor { + + private final Map directMap = new LinkedHashMap<>(); + private final Map reverseMap = new LinkedHashMap<>(); + private int size; + + + public CaesarFileCipher(String alphabet) { + char[] chars = alphabet.toCharArray(); + for (int i = 0; i < chars.length; i++) { + directMap.put(chars[i], i); + reverseMap.put(i, chars[i]); + } + size = chars.length; + } + + private byte key; + + @Override + public void setKey(byte key) { + this.key = key; + } + + + public byte getKey() { + return key; + } + @Override + public String apply(String input) { + return encrypt(input); + } + + private String encrypt(String input) { + return shift(input, key); + } + + private String decrypt(String input) { + return shift(input, (byte) -key); + } + + private String shift(String input, byte key) { + StringBuilder result = new StringBuilder(); + for (char c : input.toCharArray()) { + Integer index = directMap.get(c); + if (index != null) { + int shifted = (index + key + size) % size; + result.append(reverseMap.get(shifted)); + } else { + result.append(c); + } + } + return result.toString(); + } + + @Override + public Map> getActions() { + return Map.of( + Mode.ENCRYPT, this::encrypt, + Mode.DECRYPT, this::decrypt + ); + } +} diff --git a/src/main/resources/CaesarFileRunner.java b/src/main/resources/CaesarFileRunner.java new file mode 100644 index 0000000..fd1158a --- /dev/null +++ b/src/main/resources/CaesarFileRunner.java @@ -0,0 +1,40 @@ +package ru.javarush.lim.cryptoanalizer.io; + + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import ru.javarush.lim.cryptoanalizer.util.cipher.CaesarFileCipher; +import ru.javarush.lim.cryptoanalizer.util.cipher.Mode; +import ru.javarush.lim.cryptoanalizer.util.cipher.Process; +import ru.javarush.lim.cryptoanalizer.util.logger.Logger; +import ru.javarush.lim.cryptoanalizer.util.logger.LoggerSingleton; + +public class CaesarFileRunner { + + private static final Logger logger = LoggerSingleton.getInstance(); + + public static void run(String inputPath, String outputPath, CaesarFileCipher cipher, byte key, Mode mode) { + cipher.receiveKey(key); + logger.info("Запускаем CaesarFileRunner"); + + try (BufferedReader reader = new BufferedReader(new FileReader(inputPath)); + BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath))) { + + String line; + while ((line = reader.readLine()) != null) { + String result = cipher.process(line, mode); + writer.write(result); + writer.newLine(); + } + + logger.success("Файл успешно обработан: " + outputPath); + + } catch (IOException e) { + logger.exception("CaesarFileRunner", "Ошибка при обработке файла", e); + } + } + +} diff --git a/src/main/resources/Cipher.java b/src/main/resources/Cipher.java new file mode 100644 index 0000000..fd5e90d --- /dev/null +++ b/src/main/resources/Cipher.java @@ -0,0 +1,8 @@ + package ru.javarush.lim.cryptoanalizer.util.cipher; + + + @FunctionalInterface + public interface Cipher { + + String apply(T input); + } diff --git a/src/main/resources/ConsoleView.java b/src/main/resources/ConsoleView.java new file mode 100644 index 0000000..5cbe33f --- /dev/null +++ b/src/main/resources/ConsoleView.java @@ -0,0 +1,26 @@ +package ru.javarush.lim.cryptoanalizer.ui; + +import java.util.Scanner; +import ru.javarush.lim.cryptoanalizer.util.logger.Logger; +import ru.javarush.lim.cryptoanalizer.util.logger.LoggerSingleton; + +public class ConsoleView { + private final Scanner scanner = new Scanner(System.in); + private final Logger logger = LoggerSingleton.getInstance(); + + public void showMenu() { + logger.info("\n=== МЕНЮ ==="); + logger.info("1 — Шифровать/дешифровать файл"); + logger.info("2 — Шифровать/дешифровать текст с консоли"); + logger.info("0 — Выход"); + logger.info("Выберите действие: "); + } + + public String readChoice() { + return scanner.nextLine().trim(); + } + + public Scanner getScanner() { + return scanner; + } +} diff --git a/src/main/resources/ExtendedAcceptor.java b/src/main/resources/ExtendedAcceptor.java new file mode 100644 index 0000000..c2255d7 --- /dev/null +++ b/src/main/resources/ExtendedAcceptor.java @@ -0,0 +1,9 @@ +package ru.javarush.lim.cryptoanalizer.util.cipher; + + +public interface ExtendedAcceptor extends KeyAcceptor { + + default byte receiveKey(byte key) { + return KeyAcceptor.acceptKey(key, this); + } +} diff --git a/src/main/resources/KeyAcceptor.java b/src/main/resources/KeyAcceptor.java new file mode 100644 index 0000000..56b2db9 --- /dev/null +++ b/src/main/resources/KeyAcceptor.java @@ -0,0 +1,13 @@ +package ru.javarush.lim.cryptoanalizer.util.cipher; + +public interface KeyAcceptor extends KeyReceiver { + + static byte acceptKey(byte key, Object target) { + if (target instanceof KeyReceiver receiver) { + receiver.setKey(key); + return key; + } else { + throw new IllegalArgumentException("Target does not implement KeyReceiver"); + } + } +} diff --git a/src/main/resources/KeyReceiver.java b/src/main/resources/KeyReceiver.java new file mode 100644 index 0000000..fe0c2be --- /dev/null +++ b/src/main/resources/KeyReceiver.java @@ -0,0 +1,8 @@ +package ru.javarush.lim.cryptoanalizer.util.cipher; + +public interface KeyReceiver { + + default void setKey(byte key) { + System.out.println("[KeyReceiver] Key set to: " + key); + } +} diff --git a/src/main/resources/LogManager.java b/src/main/resources/LogManager.java new file mode 100644 index 0000000..ef55020 --- /dev/null +++ b/src/main/resources/LogManager.java @@ -0,0 +1,61 @@ +package ru.javarush.lim.cryptoanalizer.util.logger; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import ru.javarush.lim.cryptoanalizer.util.logger.LoggerStyle.LogLevel; + +public final class LogManager { + + private static final DateTimeFormatter FORMATTER = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + private static final String LOG_DIR = "logs"; + + private static Logger logger = LoggerSingleton.getInstance(); + + private LogManager() { + throw new UnsupportedOperationException("This utility class cannot be instantiated"); + } + + public static void setLogger(Logger customLogger) { + logger = customLogger; + } + + public static void log(String source, LogLevel level, String message, Throwable throwable) { + String timestamp = LocalDateTime.now().format(FORMATTER); + StringBuilder logLine = new StringBuilder( + "[%s] [%s] [%s] %s".formatted(timestamp, level, source, message)); + + if (throwable != null) { + logLine.append(" — ") + .append(throwable.getClass().getSimpleName()) + .append(": ") + .append(throwable.getMessage()); + } + + writeToFile(source, logLine.toString()); + } + + private static void writeToFile(String source, String logLine) { + String fileName = "%s.log".formatted(source); + Path logPath = Path.of(LOG_DIR, fileName); + + try { + java.nio.file.Files.createDirectories(logPath.getParent()); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(logPath.toFile(), true))) { + writer.write(logLine); + writer.newLine(); + } + } catch (IOException e) { + if (logger != null) { + logger.warn("LogManager", "Ошибка записи лога:"); + } else { + System.out.println("Ошибка записи лога: "); + } + } + } +} diff --git a/src/main/resources/Logger.java b/src/main/resources/Logger.java new file mode 100644 index 0000000..6534451 --- /dev/null +++ b/src/main/resources/Logger.java @@ -0,0 +1,24 @@ +package ru.javarush.lim.cryptoanalizer.util.logger; + +public interface Logger { + + void info(String message); + + void success(String message); + + void fail(String message); + + void debug(String source, String message); + + void warn(String source, String message); + + void error(String source, String message); + + void exception(String source, String message, Throwable throwable); + +} + + + + + diff --git a/src/main/resources/LoggerSingleton.java b/src/main/resources/LoggerSingleton.java new file mode 100644 index 0000000..7545d53 --- /dev/null +++ b/src/main/resources/LoggerSingleton.java @@ -0,0 +1,55 @@ +package ru.javarush.lim.cryptoanalizer.util.logger; + +import ru.javarush.lim.cryptoanalizer.util.logger.LoggerStyle.LogLevel; + +public final class LoggerSingleton implements Logger { + + private static final LoggerSingleton INSTANCE = new LoggerSingleton(); + + private LoggerSingleton() { + + } + + public static Logger getInstance() { + return INSTANCE; + } + + @Override + public void debug(String source, String message) { + System.out.println(LoggerStyle.formatMessage(LogLevel.DEBUG, source, message, null)); + LogManager.log(source, LogLevel.DEBUG, message, null); + } + + @Override + public void info(String message) { + System.out.println(LoggerStyle.info(message)); + } + + @Override + public void warn(String source, String message) { + System.out.println(LoggerStyle.formatMessage(LogLevel.WARN, source, message, null)); + LogManager.log(source, LogLevel.WARN, message, null); + } + + @Override + public void error(String source, String message) { + System.out.println(LoggerStyle.formatMessage(LogLevel.ERROR, source, message, null)); + LogManager.log(source, LogLevel.ERROR, message, null); + } + + @Override + public void exception(String source, String message, Throwable throwable) { + System.out.println(LoggerStyle.formatMessage(LogLevel.EXCEPTION, source, message, throwable)); + LogManager.log(source, LogLevel.EXCEPTION, message, throwable); + } + + @Override + public void success(String message) { + System.out.println(LoggerStyle.successConsole(message)); + } + + @Override + public void fail(String message) { + System.out.println(LoggerStyle.failConsole(message)); + } +} diff --git a/src/main/resources/LoggerStyle.java b/src/main/resources/LoggerStyle.java new file mode 100644 index 0000000..db2cbd0 --- /dev/null +++ b/src/main/resources/LoggerStyle.java @@ -0,0 +1,98 @@ +package ru.javarush.lim.cryptoanalizer.util.logger; + +public final class LoggerStyle { + + private LoggerStyle() { + } + + public enum TextColor { + RESET("\u001B[0m"), + BLACK("\u001B[30m"), + RED("\u001B[31m"), + GREEN("\u001B[32m"), + YELLOW("\u001B[33m"), + BLUE("\u001B[34m"), + PURPLE("\u001B[35m"), + CYAN("\u001B[36m"), + WHITE("\u001B[37m"); + + private final String code; + + TextColor(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + } + + + public enum BackgroundColor { + RESET("\u001B[0m"), + BLACK("\u001B[40m"), + RED("\u001B[41m"), + GREEN("\u001B[42m"), + YELLOW("\u001B[43m"), + BLUE("\u001B[44m"), + PURPLE("\u001B[45m"), + CYAN("\u001B[46m"), + WHITE("\u001B[47m"); + + private final String code; + + BackgroundColor(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + } + + public enum LogLevel { + DEBUG, + WARN, + ERROR, + EXCEPTION + } + + public static String formatMessage(LogLevel level, String source, String message, + Throwable throwable) { + String color = switch (level) { + case DEBUG -> TextColor.CYAN.getCode(); + case WARN -> TextColor.YELLOW.getCode(); + case ERROR, EXCEPTION -> TextColor.RED.getCode(); + }; + + String prefix = switch (level) { + case DEBUG -> "[DEBUG]"; + case WARN -> "[WARN]"; + case ERROR -> "[ERROR]"; + case EXCEPTION -> "[EXCEPTION]"; + }; + + String fullMessage = prefix + " " + source + ": " + message; + + if (throwable != null) { + fullMessage += " — " + throwable.getMessage(); + } + + return color + fullMessage + TextColor.RESET.getCode(); + } + + + public static String successConsole(String message) { + return BackgroundColor.GREEN.getCode() + TextColor.BLACK.getCode() + " " + message + " " + + TextColor.RESET.getCode(); + } + + public static String failConsole(String message) { + return BackgroundColor.RED.getCode() + TextColor.BLACK.getCode() + " " + message + " " + + TextColor.RESET.getCode(); + } + + public static String info(String message) { + return TextColor.CYAN.getCode() + message + TextColor.RESET.getCode(); + } +} \ No newline at end of file diff --git a/src/main/resources/Main.java b/src/main/resources/Main.java new file mode 100644 index 0000000..ab451b7 --- /dev/null +++ b/src/main/resources/Main.java @@ -0,0 +1,13 @@ + package ru.javarush.lim.cryptoanalizer; + + import ru.javarush.lim.cryptoanalizer.ui.MenuController; + + + public class Main { + + public static void main(String[] args) { + + new MenuController().run(); // ← это останется + + } + } \ No newline at end of file diff --git a/src/main/resources/Mapper.java b/src/main/resources/Mapper.java new file mode 100644 index 0000000..fd2df9c --- /dev/null +++ b/src/main/resources/Mapper.java @@ -0,0 +1,22 @@ +package ru.javarush.lim.cryptoanalizer.util.alphabet; + +import java.util.LinkedHashMap; +import java.util.Map; + +public interface Mapper { + + @SuppressWarnings("unchecked") + default K convert(int index) { + return (K) Integer.valueOf(index); + } + + default Map index(T[] array) { + Map map = new LinkedHashMap<>(); + for (int i = 0; i < array.length; i++) { + final int index = i; + T item = array[i]; + map.computeIfAbsent(item, k -> convert(index)); + } + return map; + } +} \ No newline at end of file diff --git a/src/main/resources/MenuController.java b/src/main/resources/MenuController.java new file mode 100644 index 0000000..51dec15 --- /dev/null +++ b/src/main/resources/MenuController.java @@ -0,0 +1,87 @@ +package ru.javarush.lim.cryptoanalizer.ui; + +import ru.javarush.lim.cryptoanalizer.io.CaesarFileRunner; +import ru.javarush.lim.cryptoanalizer.util.alphabet.AlphabetConfig; +import ru.javarush.lim.cryptoanalizer.util.cipher.CaesarFileCipher; +import ru.javarush.lim.cryptoanalizer.util.cipher.Mode; +import ru.javarush.lim.cryptoanalizer.util.logger.Logger; +import ru.javarush.lim.cryptoanalizer.util.logger.LoggerSingleton; + +import java.util.Scanner; + +public class MenuController { + private final Logger logger = LoggerSingleton.getInstance(); + private final ConsoleView view = new ConsoleView(); + private final String symbols = AlphabetConfig.RUSSIAN; + + public void run() { + while (true) { + view.showMenu(); + String choice = view.readChoice(); + + if (choice.equals("0")) { + logger.info("Выход из программы. До встречи!"); + break; + } + + handleChoice(choice); + } + } + + private void handleChoice(String choice) { + CaesarFileCipher cipher = new CaesarFileCipher(symbols); + Scanner scanner = view.getScanner(); + + if (choice.equals("1")) { + logger.info("Введите путь к входному файлу:"); + String inputPath = scanner.nextLine(); + + logger.info("Введите путь к выходному файлу:"); + String outputPath = scanner.nextLine(); + + Mode mode = readModeAndKey(scanner, cipher); + CaesarFileRunner.run(inputPath, outputPath, cipher, cipher.getKey(), mode); + + } else if (choice.equals("2")) { + logger.info("Введите текст:"); + String inputText = scanner.nextLine(); + + Mode mode = readModeAndKey(scanner, cipher); + String result = cipher.process(inputText, mode); + logger.success("Результат: " + result); + + } else { + logger.warn("Main", "❌ Неверный выбор. Попробуйте снова."); + } + } + + private Mode readModeAndKey(Scanner scanner, CaesarFileCipher cipher) { + byte key = readKey(scanner); + cipher.receiveKey(key); + return readMode(scanner); + } + + private byte readKey(Scanner scanner) { + while (true) { + logger.info("Введите ключ (целое число от -128 до 127):"); + String input = scanner.nextLine().trim(); + try { + return Byte.parseByte(input); + } catch (NumberFormatException e) { + logger.fail("❌ Неверный формат. Попробуйте снова."); + } + } + } + + private Mode readMode(Scanner scanner) { + while (true) { + logger.info("Режим (encrypt/decrypt):"); + String input = scanner.nextLine().trim().toLowerCase(); + switch (input) { + case "encrypt" -> { return Mode.ENCRYPT; } + case "decrypt" -> { return Mode.DECRYPT; } + default -> logger.fail("❌ Неверный режим. Введите 'encrypt' или 'decrypt'."); + } + } + } +} diff --git a/src/main/resources/Mode.java b/src/main/resources/Mode.java new file mode 100644 index 0000000..1de656d --- /dev/null +++ b/src/main/resources/Mode.java @@ -0,0 +1,6 @@ +package ru.javarush.lim.cryptoanalizer.util.cipher; + +public enum Mode { + ENCRYPT, + DECRYPT +} \ No newline at end of file diff --git a/src/main/resources/Parser.java b/src/main/resources/Parser.java new file mode 100644 index 0000000..daa372d --- /dev/null +++ b/src/main/resources/Parser.java @@ -0,0 +1,15 @@ +package ru.javarush.lim.cryptoanalizer.util.alphabet; + +import java.util.Optional; + +public interface Parser { + + default Optional parse(String input) { + return Optional.empty(); + } + + default T parseOrThrow(String input) { + return parse(input).orElseThrow(() -> + new IllegalArgumentException("❌ Невозможно распарсить: " + input)); + } +} \ No newline at end of file diff --git a/src/main/resources/Process.java b/src/main/resources/Process.java new file mode 100644 index 0000000..a365f29 --- /dev/null +++ b/src/main/resources/Process.java @@ -0,0 +1,24 @@ +package ru.javarush.lim.cryptoanalizer.util.cipher; + +import java.util.Map; +import java.util.function.Function; + +public interface Process { + + + + default Map> getActions() { + return Map.of( + Mode.ENCRYPT, Function.identity(), + Mode.DECRYPT, Function.identity() + ); + } + + default T process(T input, Mode mode) { + Function action = getActions().get(mode); + if (action == null) { + throw new IllegalArgumentException("Unsupported mode: " + mode); + } + return action.apply(input); + } +} diff --git a/src/main/resources/RussianAlphabet.java b/src/main/resources/RussianAlphabet.java new file mode 100644 index 0000000..603a19d --- /dev/null +++ b/src/main/resources/RussianAlphabet.java @@ -0,0 +1,16 @@ +package ru.javarush.lim.cryptoanalizer.util.alphabet; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class RussianAlphabet implements Alphabet { + + @Override + public Map build(String symbols) { + Character[] array = symbols.chars() + .mapToObj(c -> (char) c) + .toArray(Character[]::new); + + return index(array); + } +} diff --git a/src/main/resources/pom.xml b/src/main/resources/pom.xml new file mode 100644 index 0000000..9fc491f --- /dev/null +++ b/src/main/resources/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + com.javarush.khmelov + cryptoanalyzer + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.5.4 + + + + + 21 + 21 + UTF-8 + 1.1 + + + + + + info.picocli + picocli + 4.6.3 + + + + org.apache.commons + commons-math3 + 3.6.1 + + + \ No newline at end of file