mirror of
https://github.com/OtusTeam/Spring.git
synced 2026-05-30 10:50:42 +00:00
2022-02 spring-00/architecture-origins added
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>architecture-origins</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>solution01</module>
|
||||
<module>solution02_codeface</module>
|
||||
<module>solution03_kiss</module>
|
||||
<module>solution04_kiss</module>
|
||||
<module>solution05_dry</module>
|
||||
<module>solution06_dry</module>
|
||||
<module>solution07_srp</module>
|
||||
<module>solution08_srp</module>
|
||||
<module>solution09_dip</module>
|
||||
<module>solution10_ocp_isp</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution01</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,65 @@
|
||||
package ru.otus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<String> strings = new ArrayList<>();
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
while (true) {
|
||||
System.out.println("Выберите одно из следующих действий...");
|
||||
System.out.println("1. Вывести все заметки");
|
||||
System.out.println("2. Добавить заметку");
|
||||
System.out.println("3. Изменить заметку");
|
||||
System.out.println("4. Удалить заметку");
|
||||
System.out.println("5. Выйти");
|
||||
|
||||
try {
|
||||
int i = Integer.parseInt(sc.nextLine());
|
||||
|
||||
if (i == 1) {
|
||||
System.out.println("Заметки:");
|
||||
IntStream.range(1, strings.size() + 1)
|
||||
.mapToObj(k -> k + " | " + strings.get(k - 1))
|
||||
.forEach(System.out::println);
|
||||
System.out.println();
|
||||
} else if (i == 2) {
|
||||
System.out.println("Введите текст заметки...");
|
||||
String s = sc.nextLine();
|
||||
strings.add(LocalDateTime.now() + " | " + s);
|
||||
} else if (i == 3) {
|
||||
System.out.println("Введите номер изменяемой заметки...");
|
||||
int k = Integer.parseInt(sc.nextLine());
|
||||
;
|
||||
if (k > 0 && k <= strings.size()) {
|
||||
System.out.println("Введите текст заметки...");
|
||||
String s = sc.nextLine();
|
||||
strings.set(k - 1, LocalDateTime.now() + " | " + s);
|
||||
} else {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
}
|
||||
} else if (i == 4) {
|
||||
System.out.println("Введите номер удаляемой заметки...");
|
||||
int k = Integer.parseInt(sc.nextLine());
|
||||
if (k > 0 && k <= strings.size()) {
|
||||
strings.remove(k - 1);
|
||||
} else {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
}
|
||||
} else if (i == 5) {
|
||||
break;
|
||||
} else {
|
||||
System.out.println("Введен неверный номер опции");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Ошибка при вводе числа");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution02_codeface</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package ru.otus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
// Имена переменных, константы, выпрямление кода
|
||||
public class Main {
|
||||
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
var notes = new ArrayList<String>();
|
||||
var userInput = new Scanner(System.in);
|
||||
|
||||
while (true) {
|
||||
System.out.println("Выберите одно из следующих действий...");
|
||||
System.out.println("1. Вывести все заметки");
|
||||
System.out.println("2. Добавить заметку");
|
||||
System.out.println("3. Изменить заметку");
|
||||
System.out.println("4. Удалить заметку");
|
||||
System.out.println("5. Выйти");
|
||||
|
||||
try {
|
||||
var selectedOptionNumber = Integer.parseInt(userInput.nextLine());
|
||||
|
||||
if (selectedOptionNumber == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
System.out.println("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> k + " | " + notes.get(k - 1))
|
||||
.forEach(System.out::println);
|
||||
System.out.println();
|
||||
} else if (selectedOptionNumber == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
System.out.println("Введите текст заметки...");
|
||||
var noteText = userInput.nextLine();
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.add(finalNoteText);
|
||||
} else if (selectedOptionNumber == MENU_OPTION_UPDATE_NOTE) {
|
||||
System.out.println("Введите номер изменяемой заметки...");
|
||||
|
||||
var updatedNoteNumber = Integer.parseInt(userInput.nextLine());
|
||||
|
||||
if (updatedNoteNumber <= 0 || updatedNoteNumber > notes.size()) {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.println("Введите текст заметки...");
|
||||
var noteText = userInput.nextLine();
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.set(updatedNoteNumber - 1, finalNoteText);
|
||||
} else if (selectedOptionNumber == MENU_OPTION_DELETE_NOTE) {
|
||||
System.out.println("Введите номер удаляемой заметки...");
|
||||
|
||||
var deletedNoteNumber = Integer.parseInt(userInput.nextLine());
|
||||
if (deletedNoteNumber <= 0 || deletedNoteNumber > notes.size()) {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
continue;
|
||||
}
|
||||
|
||||
notes.remove(deletedNoteNumber - 1);
|
||||
} else if (selectedOptionNumber == MENU_OPTION_EXIT) {
|
||||
break;
|
||||
} else {
|
||||
System.out.println("Введен неверный номер опции");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Ошибка при вводе числа");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution03_kiss</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package ru.otus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
// Вынос печати меню, чтения пункта меню и выполнения команд в методы
|
||||
public class Main {
|
||||
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
var notes = new ArrayList<String>();
|
||||
var userInput = new Scanner(System.in);
|
||||
|
||||
while (true) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumberFrom(userInput);
|
||||
|
||||
if (selectedMenuItem == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
showAllNotes(notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
addNewNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_UPDATE_NOTE) {
|
||||
updateNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_DELETE_NOTE) {
|
||||
deleteNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_EXIT){
|
||||
break;
|
||||
} else {
|
||||
System.out.println("Введен неверный номер опции");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Ошибка при вводе числа");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void outputMenu(){
|
||||
System.out.println("Выберите одно из следующих действий...");
|
||||
System.out.println("1. Вывести все заметки");
|
||||
System.out.println("2. Добавить заметку");
|
||||
System.out.println("3. Изменить заметку");
|
||||
System.out.println("4. Удалить заметку");
|
||||
System.out.println("5. Выйти");
|
||||
}
|
||||
|
||||
private static int readSelectedOptionNumberFrom(Scanner userInput) {
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
private static void showAllNotes(List<String> notes) {
|
||||
System.out.println("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> k + " | " + notes.get(k - 1))
|
||||
.forEach(System.out::println);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static void addNewNote(Scanner userInput, List<String> notes) {
|
||||
System.out.println("Введите текст заметки...");
|
||||
var noteText = userInput.nextLine();
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.add(finalNoteText);
|
||||
}
|
||||
|
||||
private static void updateNote(Scanner userInput, List<String> notes) {
|
||||
System.out.println("Введите номер изменяемой заметки...");
|
||||
|
||||
var updatedNoteNumber = Integer.parseInt(userInput.nextLine());;
|
||||
if (updatedNoteNumber <= 0 || updatedNoteNumber > notes.size()) {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Введите текст заметки...");
|
||||
var noteText = userInput.nextLine();
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.set(updatedNoteNumber - 1, finalNoteText);
|
||||
}
|
||||
|
||||
private static void deleteNote(Scanner userInput, List<String> notes) {
|
||||
System.out.println("Введите номер удаляемой заметки...");
|
||||
|
||||
var deletedNoteNumber = Integer.parseInt(userInput.nextLine());
|
||||
if (deletedNoteNumber <= 0 || deletedNoteNumber > notes.size()) {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
return;
|
||||
}
|
||||
|
||||
notes.remove(deletedNoteNumber - 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution04_kiss</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package ru.otus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
// Уменьшение вложенности в main за счет выноса обработки команд в метод + executionFlag
|
||||
public class Main {
|
||||
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
var notes = new ArrayList<String>();
|
||||
var userInput = new Scanner(System.in);
|
||||
|
||||
var executionFlag = new AtomicBoolean(true);
|
||||
while (executionFlag.get()) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumberFrom(userInput);
|
||||
processMenuCommand(selectedMenuItem, executionFlag, userInput, notes);
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Ошибка при вводе числа");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void outputMenu(){
|
||||
System.out.println("Выберите одно из следующих действий...");
|
||||
System.out.println("1. Вывести все заметки");
|
||||
System.out.println("2. Добавить заметку");
|
||||
System.out.println("3. Изменить заметку");
|
||||
System.out.println("4. Удалить заметку");
|
||||
System.out.println("5. Выйти");
|
||||
}
|
||||
|
||||
private static void processMenuCommand(int selectedMenuItem, AtomicBoolean executionFlag,
|
||||
Scanner userInput, List<String> notes) {
|
||||
if (selectedMenuItem == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
showAllNotes(notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
addNewNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_UPDATE_NOTE) {
|
||||
updateNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_DELETE_NOTE) {
|
||||
deleteNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_EXIT){
|
||||
executionFlag.set(false);
|
||||
} else {
|
||||
System.out.println("Введен неверный номер опции");
|
||||
}
|
||||
}
|
||||
|
||||
private static int readSelectedOptionNumberFrom(Scanner userInput) {
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
private static void showAllNotes(List<String> notes) {
|
||||
System.out.println("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> k + " | " + notes.get(k - 1))
|
||||
.forEach(System.out::println);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static void addNewNote(Scanner userInput, List<String> notes) {
|
||||
System.out.println("Введите текст заметки...");
|
||||
var noteText = userInput.nextLine();
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.add(finalNoteText);
|
||||
}
|
||||
|
||||
private static void updateNote(Scanner userInput, List<String> notes) {
|
||||
System.out.println("Введите номер изменяемой заметки...");
|
||||
|
||||
var updatedNoteNumber = Integer.parseInt(userInput.nextLine());;
|
||||
if (updatedNoteNumber <= 0 || updatedNoteNumber > notes.size()) {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Введите текст заметки...");
|
||||
var noteText = userInput.nextLine();
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.set(updatedNoteNumber - 1, finalNoteText);
|
||||
}
|
||||
|
||||
private static void deleteNote(Scanner userInput, List<String> notes) {
|
||||
System.out.println("Введите номер удаляемой заметки...");
|
||||
|
||||
var deletedNoteNumber = Integer.parseInt(userInput.nextLine());
|
||||
if (deletedNoteNumber <= 0 || deletedNoteNumber > notes.size()) {
|
||||
System.out.println("Введен несуществующий номер заметки");
|
||||
return;
|
||||
}
|
||||
|
||||
notes.remove(deletedNoteNumber - 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution05_dry</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
package ru.otus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
// Вынос логики ввода-вывода
|
||||
public class Main {
|
||||
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
var notes = new ArrayList<String>();
|
||||
var userInput = new Scanner(System.in);
|
||||
|
||||
var executionFlag = new AtomicBoolean(true);
|
||||
while (executionFlag.get()) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumberFrom(userInput);
|
||||
processMenuCommand(selectedMenuItem, executionFlag, userInput, notes);
|
||||
} catch (NumberFormatException e) {
|
||||
outputString("Ошибка при вводе числа");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void outputMenu(){
|
||||
outputString("Выберите одно из следующих действий...");
|
||||
outputString("1. Вывести все заметки");
|
||||
outputString("2. Добавить заметку");
|
||||
outputString("3. Изменить заметку");
|
||||
outputString("4. Удалить заметку");
|
||||
outputString("5. Выйти");
|
||||
}
|
||||
|
||||
private static void processMenuCommand(int selectedMenuItem, AtomicBoolean executionFlag,
|
||||
Scanner userInput, List<String> notes) {
|
||||
if (selectedMenuItem == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
showAllNotes(notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
addNewNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_UPDATE_NOTE) {
|
||||
updateNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_DELETE_NOTE) {
|
||||
deleteNote(userInput, notes);
|
||||
} else if (selectedMenuItem == MENU_OPTION_EXIT){
|
||||
executionFlag.set(false);
|
||||
} else {
|
||||
outputString("Введен неверный номер опции");
|
||||
}
|
||||
}
|
||||
|
||||
private static int readSelectedOptionNumberFrom(Scanner userInput) {
|
||||
return readInt(userInput);
|
||||
}
|
||||
|
||||
private static void showAllNotes(List<String> notes) {
|
||||
outputString("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> k + " | " + notes.get(k - 1))
|
||||
.forEach(Main::outputString);
|
||||
outputString("");
|
||||
}
|
||||
|
||||
private static void addNewNote(Scanner userInput, List<String> notes) {
|
||||
var noteText = readStringWithPrompt(userInput, "Введите текст заметки...");
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.add(finalNoteText);
|
||||
}
|
||||
|
||||
private static void updateNote(Scanner userInput, List<String> notes) {
|
||||
int updatedNoteNumber = readIntWithPrompt(userInput, "Введите номер изменяемой заметки...");
|
||||
if (updatedNoteNumber <= 0 || updatedNoteNumber > notes.size()) {
|
||||
outputString("Введен несуществующий номер заметки");
|
||||
return;
|
||||
}
|
||||
var noteText = readStringWithPrompt(userInput, "Введите текст заметки...");
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.set(updatedNoteNumber - 1, finalNoteText);
|
||||
}
|
||||
|
||||
private static void deleteNote(Scanner userInput, List<String> notes) {
|
||||
var deletedNoteNumber = readIntWithPrompt(userInput, "Введите номер удаляемой заметки...");
|
||||
if (deletedNoteNumber <= 0 || deletedNoteNumber > notes.size()) {
|
||||
outputString("Введен несуществующий номер заметки");
|
||||
return;
|
||||
}
|
||||
|
||||
notes.remove(deletedNoteNumber - 1);
|
||||
}
|
||||
|
||||
private static void outputString(String s){
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
private static int readInt(Scanner userInput){
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
private static int readIntWithPrompt(Scanner userInput, String prompt){
|
||||
outputString(prompt);
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
private static String readStringWithPrompt(Scanner userInput, String prompt){
|
||||
outputString(prompt);
|
||||
return userInput.nextLine();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution06_dry</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
package ru.otus;
|
||||
|
||||
import ru.otus.exceptions.MenuItemIndexOutOfBoundsException;
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
// Вынос проверки существования выбранной команды в метод checkNoteNumber,
|
||||
// централизованная обработка ошибок
|
||||
public class Main {
|
||||
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
var notes = new ArrayList<String>();
|
||||
var userInput = new Scanner(System.in);
|
||||
|
||||
var executionFlag = new AtomicBoolean(true);
|
||||
while (executionFlag.get()) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumberFrom(userInput);
|
||||
processMenuCommand(selectedMenuItem, executionFlag, userInput, notes);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
outputString("Ошибка при вводе числа");
|
||||
} catch (MenuItemIndexOutOfBoundsException e) {
|
||||
outputString("Введен неверный номер опции");
|
||||
} catch (NoteIndexOutOfBoundsException e) {
|
||||
outputString("Введен несуществующий номер заметки");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void outputMenu(){
|
||||
outputString("Выберите одно из следующих действий...");
|
||||
outputString("1. Вывести все заметки");
|
||||
outputString("2. Добавить заметку");
|
||||
outputString("3. Изменить заметку");
|
||||
outputString("4. Удалить заметку");
|
||||
outputString("5. Выйти");
|
||||
}
|
||||
|
||||
private static void processMenuCommand(int selectedMenuItemIndex, AtomicBoolean executionFlag,
|
||||
Scanner userInput, List<String> notes) {
|
||||
if (selectedMenuItemIndex == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
showAllNotes(notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
addNewNote(userInput, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_UPDATE_NOTE) {
|
||||
updateNote(userInput, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_DELETE_NOTE) {
|
||||
deleteNote(userInput, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_EXIT){
|
||||
executionFlag.set(false);
|
||||
} else {
|
||||
throw new MenuItemIndexOutOfBoundsException("Given menu item index is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
private static int readSelectedOptionNumberFrom(Scanner userInput) {
|
||||
return readInt(userInput);
|
||||
}
|
||||
|
||||
private static void showAllNotes(List<String> notes) {
|
||||
outputString("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> k + " | " + notes.get(k - 1))
|
||||
.forEach(Main::outputString);
|
||||
outputString("");
|
||||
}
|
||||
|
||||
private static void addNewNote(Scanner userInput, List<String> notes) {
|
||||
var noteText = readStringWithPrompt(userInput, "Введите текст заметки...");
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.add(finalNoteText);
|
||||
}
|
||||
|
||||
private static void checkNoteNumber(int noteNumber, List<String> notes) {
|
||||
if (noteNumber <= 0 || noteNumber > notes.size()) {
|
||||
throw new NoteIndexOutOfBoundsException("Given number of note is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateNote(Scanner userInput, List<String> notes) {
|
||||
var updatedNoteNumber = readIntWithPrompt(userInput, "Введите номер изменяемой заметки...");
|
||||
checkNoteNumber(updatedNoteNumber, notes);
|
||||
|
||||
var noteText = readStringWithPrompt(userInput, "Введите текст заметки...");
|
||||
var finalNoteText = LocalDateTime.now() + " | " + noteText;
|
||||
notes.set(updatedNoteNumber - 1, finalNoteText);
|
||||
}
|
||||
|
||||
private static void deleteNote(Scanner userInput, List<String> notes) {
|
||||
var deletedNoteNumber = readIntWithPrompt(userInput, "Введите номер удаляемой заметки...");
|
||||
checkNoteNumber(deletedNoteNumber, notes);
|
||||
|
||||
notes.remove(deletedNoteNumber - 1);
|
||||
}
|
||||
|
||||
private static void outputString(String s){
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
private static int readInt(Scanner userInput){
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
private static int readIntWithPrompt(Scanner userInput, String prompt){
|
||||
outputString(prompt);
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
private static String readStringWithPrompt(Scanner userInput, String prompt){
|
||||
outputString(prompt);
|
||||
return userInput.nextLine();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class MenuItemIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public MenuItemIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class NoteIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public NoteIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution07_srp</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package ru.otus;
|
||||
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
import ru.otus.exceptions.MenuItemIndexOutOfBoundsException;
|
||||
import ru.otus.model.Note;
|
||||
import ru.otus.services.ConsoleIOService;
|
||||
import ru.otus.services.NoteConverter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
// Note, ConsoleIOService, NoteConverter
|
||||
public class Main {
|
||||
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
var notes = new ArrayList<Note>();
|
||||
var ioService = new ConsoleIOService();
|
||||
|
||||
var executionFlag = new AtomicBoolean(true);
|
||||
while (executionFlag.get()) {
|
||||
outputMenu(ioService);
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumberFrom(ioService);
|
||||
processMenuCommand(selectedMenuItem, executionFlag, ioService, notes);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
ioService.outputString("Ошибка при вводе числа");
|
||||
} catch (MenuItemIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен неверный номер опции");
|
||||
} catch (NoteIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен несуществующий номер заметки");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void outputMenu(ConsoleIOService ioService){
|
||||
ioService.outputString("Выберите одно из следующих действий...");
|
||||
ioService.outputString("1. Вывести все заметки");
|
||||
ioService.outputString("2. Добавить заметку");
|
||||
ioService.outputString("3. Изменить заметку");
|
||||
ioService.outputString("4. Удалить заметку");
|
||||
ioService.outputString("5. Выйти");
|
||||
}
|
||||
|
||||
private static void processMenuCommand(int selectedMenuItemIndex, AtomicBoolean executionFlag,
|
||||
ConsoleIOService ioService, List<Note> notes) {
|
||||
if (selectedMenuItemIndex == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
showAllNotes(ioService, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
addNewNote(ioService, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_UPDATE_NOTE) {
|
||||
updateNote(ioService, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_DELETE_NOTE) {
|
||||
deleteNote(ioService, notes);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_EXIT){
|
||||
executionFlag.set(false);
|
||||
} else {
|
||||
throw new MenuItemIndexOutOfBoundsException("Given menu item index is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
private static int readSelectedOptionNumberFrom(ConsoleIOService ioService) {
|
||||
return ioService.readInt();
|
||||
}
|
||||
|
||||
private static void showAllNotes(ConsoleIOService ioService, List<Note> notes) {
|
||||
var noteConverter = new NoteConverter();
|
||||
ioService.outputString("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> noteConverter.convertNoteToString(k, notes.get(k - 1)))
|
||||
.forEach(ioService::outputString);
|
||||
ioService.outputString("");
|
||||
}
|
||||
|
||||
private static void addNewNote(ConsoleIOService ioService, List<Note> notes) {
|
||||
var noteText = ioService.readStringWithPrompt("Введите текст заметки...");
|
||||
notes.add( Note.of(noteText));
|
||||
}
|
||||
|
||||
private static void checkNoteNumber(int noteNumber, List<Note> notes) {
|
||||
if (noteNumber <= 0 || noteNumber > notes.size()) {
|
||||
throw new NoteIndexOutOfBoundsException("Given number of note is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateNote(ConsoleIOService ioService, List<Note> notes) {
|
||||
var updatedNoteNumber = ioService.readIntWithPrompt("Введите номер изменяемой заметки...");
|
||||
checkNoteNumber(updatedNoteNumber, notes);
|
||||
|
||||
var noteText = ioService.readStringWithPrompt("Введите текст заметки...");
|
||||
notes.set(updatedNoteNumber - 1, Note.of(noteText));
|
||||
}
|
||||
|
||||
private static void deleteNote(ConsoleIOService ioService, List<Note> notes) {
|
||||
var deletedNoteNumber = ioService.readIntWithPrompt("Введите номер удаляемой заметки...");
|
||||
checkNoteNumber(deletedNoteNumber, notes);
|
||||
|
||||
notes.remove(deletedNoteNumber - 1);
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class MenuItemIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public MenuItemIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class NoteIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public NoteIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package ru.otus.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class Note {
|
||||
private final LocalDateTime creationTime;
|
||||
private final String text;
|
||||
|
||||
public Note(String text) {
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public static Note of(String text) {
|
||||
return new Note(text);
|
||||
}
|
||||
|
||||
public LocalDateTime getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class ConsoleIOService {
|
||||
private final Scanner userInput;
|
||||
|
||||
public ConsoleIOService() {
|
||||
userInput = new Scanner(System.in);
|
||||
}
|
||||
|
||||
public void outputString(String s){
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
public int readInt(){
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
public int readIntWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
public String readStringWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return userInput.nextLine();
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
public class NoteConverter {
|
||||
public String convertNoteToString(int noteNumber, Note note) {
|
||||
return noteNumber + " | " + note.getCreationTime() + " | " + note.getText();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution08_srp</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
package ru.otus;
|
||||
|
||||
import ru.otus.services.ApplicationRunner;
|
||||
|
||||
// ApplicationRunner, MenuCommandsProcessor, NotesService
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
new ApplicationRunner().run();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class MenuItemIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public MenuItemIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class NoteIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public NoteIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package ru.otus.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Note {
|
||||
private final String id;
|
||||
private final LocalDateTime creationTime;
|
||||
private final String text;
|
||||
|
||||
public Note(String text) {
|
||||
this.id = UUID.randomUUID().toString();
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Note(String id, String text) {
|
||||
this.id = id;
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Note(String id, LocalDateTime creationTime, String text) {
|
||||
this.id = id;
|
||||
this.creationTime = creationTime;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public static Note of(String text) {
|
||||
return new Note(text);
|
||||
}
|
||||
|
||||
public static Note of(String id, String text) {
|
||||
return new Note(id, text);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public Note copy() {
|
||||
return new Note(id, creationTime, text);
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.exceptions.MenuItemIndexOutOfBoundsException;
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ApplicationRunner {
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
private final ConsoleIOService ioService;
|
||||
private final AtomicBoolean executionFlag;
|
||||
private final MenuCommandsProcessor commandsProcessor;
|
||||
|
||||
|
||||
public ApplicationRunner() {
|
||||
ioService = new ConsoleIOService();
|
||||
executionFlag = new AtomicBoolean(true);
|
||||
commandsProcessor = new MenuCommandsProcessor();
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (executionFlag.get()) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumber();
|
||||
processMenuCommand(selectedMenuItem);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
ioService.outputString("Ошибка при вводе числа");
|
||||
} catch (MenuItemIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен неверный номер опции");
|
||||
} catch (NoteIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен несуществующий номер заметки");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void outputMenu(){
|
||||
ioService.outputString("Выберите одно из следующих действий...");
|
||||
ioService.outputString("1. Вывести все заметки");
|
||||
ioService.outputString("2. Добавить заметку");
|
||||
ioService.outputString("3. Изменить заметку");
|
||||
ioService.outputString("4. Удалить заметку");
|
||||
ioService.outputString("5. Выйти");
|
||||
}
|
||||
|
||||
private void processMenuCommand(int selectedMenuItemIndex) {
|
||||
if (selectedMenuItemIndex == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
commandsProcessor.showAllNotes(ioService);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
commandsProcessor.addNewNote(ioService);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_UPDATE_NOTE) {
|
||||
commandsProcessor.updateNote(ioService);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_DELETE_NOTE) {
|
||||
commandsProcessor.deleteNote(ioService);
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_EXIT){
|
||||
executionFlag.set(false);
|
||||
} else {
|
||||
throw new MenuItemIndexOutOfBoundsException("Given menu item index is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
private int readSelectedOptionNumber() {
|
||||
return ioService.readInt();
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class ConsoleIOService {
|
||||
private final Scanner userInput;
|
||||
|
||||
public ConsoleIOService() {
|
||||
userInput = new Scanner(System.in);
|
||||
}
|
||||
|
||||
public void outputString(String s){
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
public int readInt(){
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
public int readIntWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return Integer.parseInt(userInput.nextLine());
|
||||
}
|
||||
|
||||
public String readStringWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return userInput.nextLine();
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class MenuCommandsProcessor {
|
||||
private final NotesService notesService;
|
||||
|
||||
public MenuCommandsProcessor() {
|
||||
notesService = new NotesService();
|
||||
}
|
||||
|
||||
public void showAllNotes(ConsoleIOService ioService) {
|
||||
var noteConverter = new NoteConverter();
|
||||
var notes = notesService.getAll();
|
||||
ioService.outputString("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> noteConverter.convertNoteToString(k, notes.get(k - 1)))
|
||||
.forEach(ioService::outputString);
|
||||
ioService.outputString("");
|
||||
}
|
||||
|
||||
public void addNewNote(ConsoleIOService ioService) {
|
||||
var noteText = ioService.readStringWithPrompt("Введите текст заметки...");
|
||||
notesService.save(Note.of(noteText));
|
||||
}
|
||||
|
||||
public void updateNote(ConsoleIOService ioService) {
|
||||
var notes = notesService.getAll();
|
||||
|
||||
var updatedNoteNumber = ioService.readIntWithPrompt("Введите номер изменяемой заметки...");
|
||||
checkNoteNumber(updatedNoteNumber, notes.size());
|
||||
|
||||
var noteText = ioService.readStringWithPrompt("Введите текст заметки...");
|
||||
|
||||
var updatedNote = notes.get(updatedNoteNumber - 1);
|
||||
notesService.save(Note.of(updatedNote.getId(), noteText));
|
||||
}
|
||||
|
||||
public void deleteNote(ConsoleIOService ioService) {
|
||||
var notes = notesService.getAll();
|
||||
|
||||
var deletedNoteNumber = ioService.readIntWithPrompt("Введите номер удаляемой заметки...");
|
||||
checkNoteNumber(deletedNoteNumber, notes.size());
|
||||
|
||||
var updatedNote = notes.get(deletedNoteNumber - 1);
|
||||
notesService.remove(updatedNote.getId());
|
||||
}
|
||||
|
||||
private static void checkNoteNumber(int noteNumber, int notesCount) {
|
||||
if (noteNumber <= 0 || noteNumber > notesCount) {
|
||||
throw new NoteIndexOutOfBoundsException("Given number of note is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
public class NoteConverter {
|
||||
public String convertNoteToString(int noteNumber, Note note) {
|
||||
return noteNumber + " | " + note.getCreationTime() + " | " + note.getText();
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NotesService {
|
||||
private final Map<String, Note> notes;
|
||||
|
||||
public NotesService() {
|
||||
notes = new HashMap<>();
|
||||
}
|
||||
|
||||
public List<Note> getAll() {
|
||||
return notes.values().stream().map(Note::copy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void save(Note note) {
|
||||
notes.put(note.getId(), note);
|
||||
}
|
||||
|
||||
public void remove(String id) {
|
||||
notes.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution09_dip</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,20 @@
|
||||
package ru.otus;
|
||||
|
||||
import ru.otus.config.AppSettings;
|
||||
import ru.otus.services.*;
|
||||
|
||||
// +AppSettings
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
var appSettings = new AppSettings(true, "dd.mm.YYYY HH:mm:ss");
|
||||
var ioService = new IOServiceStreams(System.out, System.in);
|
||||
var applicationStopService = new ApplicationStopServiceImpl(ioService, appSettings);
|
||||
var notesService = new NotesServiceImpl();
|
||||
var noteConverter = new NoteConverterImpl(appSettings);
|
||||
var menuCommandsProcessor = new MenuCommandsProcessorImpl(ioService, notesService,
|
||||
noteConverter, applicationStopService);
|
||||
|
||||
new ApplicationRunner(ioService, applicationStopService, menuCommandsProcessor)
|
||||
.run();
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package ru.otus.config;
|
||||
|
||||
public class AppSettings {
|
||||
private final boolean confirmExit;
|
||||
private final String dateTimeFormat;
|
||||
|
||||
public AppSettings(boolean confirmExit, String dateTimeFormat) {
|
||||
this.confirmExit = confirmExit;
|
||||
this.dateTimeFormat = dateTimeFormat;
|
||||
}
|
||||
|
||||
public boolean isConfirmExit() {
|
||||
return confirmExit;
|
||||
}
|
||||
|
||||
public String getDateTimeFormat() {
|
||||
return dateTimeFormat;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class MenuItemIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public MenuItemIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class NoteIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public NoteIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package ru.otus.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Note {
|
||||
private final String id;
|
||||
private final LocalDateTime creationTime;
|
||||
private final String text;
|
||||
|
||||
public Note(String text) {
|
||||
this.id = UUID.randomUUID().toString();
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Note(String id, String text) {
|
||||
this.id = id;
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Note(String id, LocalDateTime creationTime, String text) {
|
||||
this.id = id;
|
||||
this.creationTime = creationTime;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public static Note of(String text) {
|
||||
return new Note(text);
|
||||
}
|
||||
|
||||
public static Note of(String id, String text) {
|
||||
return new Note(id, text);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public Note copy() {
|
||||
return new Note(id, creationTime, text);
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.exceptions.MenuItemIndexOutOfBoundsException;
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
|
||||
public class ApplicationRunner {
|
||||
private static final int MENU_OPTION_SHOW_ALL_NOTES = 1;
|
||||
private static final int MENU_OPTION_ADD_NEW_NOTE = 2;
|
||||
private static final int MENU_OPTION_UPDATE_NOTE = 3;
|
||||
private static final int MENU_OPTION_DELETE_NOTE = 4;
|
||||
private static final int MENU_OPTION_EXIT = 5;
|
||||
|
||||
private final IOService ioService;
|
||||
private final ApplicationStopService applicationStopService;
|
||||
private final MenuCommandsProcessor commandsProcessor;
|
||||
|
||||
|
||||
public ApplicationRunner(IOService ioService,
|
||||
ApplicationStopService applicationStopService,
|
||||
MenuCommandsProcessor commandsProcessor) {
|
||||
this.ioService = ioService;
|
||||
this.applicationStopService = applicationStopService;
|
||||
this.commandsProcessor = commandsProcessor;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (applicationStopService.isApplicationRunning()) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumber();
|
||||
processMenuCommand(selectedMenuItem);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
ioService.outputString("Ошибка при вводе числа");
|
||||
} catch (MenuItemIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен неверный номер опции");
|
||||
} catch (NoteIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен несуществующий номер заметки");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void outputMenu(){
|
||||
ioService.outputString("Выберите одно из следующих действий...");
|
||||
ioService.outputString("1. Вывести все заметки");
|
||||
ioService.outputString("2. Добавить заметку");
|
||||
ioService.outputString("3. Изменить заметку");
|
||||
ioService.outputString("4. Удалить заметку");
|
||||
ioService.outputString("5. Выйти");
|
||||
}
|
||||
|
||||
private void processMenuCommand(int selectedMenuItemIndex) {
|
||||
if (selectedMenuItemIndex == MENU_OPTION_SHOW_ALL_NOTES) {
|
||||
commandsProcessor.showAllNotes();
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_ADD_NEW_NOTE) {
|
||||
commandsProcessor.addNewNote();
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_UPDATE_NOTE) {
|
||||
commandsProcessor.updateNote();
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_DELETE_NOTE) {
|
||||
commandsProcessor.deleteNote();
|
||||
} else if (selectedMenuItemIndex == MENU_OPTION_EXIT){
|
||||
commandsProcessor.stopApplication();
|
||||
} else {
|
||||
throw new MenuItemIndexOutOfBoundsException("Given menu item index is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
private int readSelectedOptionNumber() {
|
||||
return ioService.readInt();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package ru.otus.services;
|
||||
|
||||
public interface ApplicationStopService {
|
||||
boolean isApplicationRunning();
|
||||
void stopApplication();
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.config.AppSettings;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ApplicationStopServiceImpl implements ApplicationStopService {
|
||||
|
||||
private final IOService ioService;
|
||||
private final AppSettings appSettings;
|
||||
private final AtomicBoolean executionFlag;
|
||||
|
||||
public ApplicationStopServiceImpl(IOService ioService, AppSettings appSettings) {
|
||||
this.ioService = ioService;
|
||||
this.appSettings = appSettings;
|
||||
this.executionFlag = new AtomicBoolean(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicationRunning() {
|
||||
return executionFlag.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopApplication() {
|
||||
if (appSettings.isConfirmExit()) {
|
||||
var exitConfirmation = ioService.readStringWithPrompt("Действительно выйти? (да/нет)");
|
||||
if (exitConfirmation.equalsIgnoreCase("нет")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
executionFlag.set(false);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package ru.otus.services;
|
||||
|
||||
public interface IOService {
|
||||
void outputString(String s);
|
||||
|
||||
int readInt();
|
||||
|
||||
int readIntWithPrompt(String prompt);
|
||||
|
||||
String readStringWithPrompt(String prompt);
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class IOServiceStreams implements IOService {
|
||||
private final PrintStream output;
|
||||
private final Scanner input;
|
||||
|
||||
public IOServiceStreams(PrintStream outputStream, InputStream inputStream) {
|
||||
output = outputStream;
|
||||
input = new Scanner(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outputString(String s){
|
||||
output.println(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt(){
|
||||
return Integer.parseInt(input.nextLine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readIntWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return Integer.parseInt(input.nextLine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readStringWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return input.nextLine();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package ru.otus.services;
|
||||
|
||||
public interface MenuCommandsProcessor {
|
||||
void showAllNotes();
|
||||
|
||||
void addNewNote();
|
||||
|
||||
void updateNote();
|
||||
|
||||
void deleteNote();
|
||||
|
||||
void stopApplication();
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class MenuCommandsProcessorImpl implements MenuCommandsProcessor {
|
||||
private final IOService ioService;
|
||||
private final NotesService notesService;
|
||||
private final NoteConverter noteConverter;
|
||||
private final ApplicationStopService applicationStopService;
|
||||
|
||||
public MenuCommandsProcessorImpl(IOService ioService, NotesService notesService,
|
||||
NoteConverter noteConverter,
|
||||
ApplicationStopService applicationStopService) {
|
||||
this.ioService = ioService;
|
||||
this.notesService = notesService;
|
||||
this.noteConverter = noteConverter;
|
||||
this.applicationStopService = applicationStopService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showAllNotes() {
|
||||
var notes = notesService.getAll();
|
||||
ioService.outputString("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> noteConverter.convertNoteToString(k, notes.get(k - 1)))
|
||||
.forEach(ioService::outputString);
|
||||
ioService.outputString("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewNote() {
|
||||
var noteText = ioService.readStringWithPrompt("Введите текст заметки...");
|
||||
notesService.save(Note.of(noteText));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNote() {
|
||||
var notes = notesService.getAll();
|
||||
|
||||
var updatedNoteNumber = ioService.readIntWithPrompt("Введите номер изменяемой заметки...");
|
||||
checkNoteNumber(updatedNoteNumber, notes.size());
|
||||
|
||||
var noteText = ioService.readStringWithPrompt("Введите текст заметки...");
|
||||
|
||||
var updatedNote = notes.get(updatedNoteNumber - 1);
|
||||
notesService.save(Note.of(updatedNote.getId(), noteText));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteNote() {
|
||||
var notes = notesService.getAll();
|
||||
|
||||
var deletedNoteNumber = ioService.readIntWithPrompt("Введите номер удаляемой заметки...");
|
||||
checkNoteNumber(deletedNoteNumber, notes.size());
|
||||
|
||||
var updatedNote = notes.get(deletedNoteNumber - 1);
|
||||
notesService.remove(updatedNote.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopApplication() {
|
||||
applicationStopService.stopApplication();
|
||||
}
|
||||
|
||||
private static void checkNoteNumber(int noteNumber, int notesCount) {
|
||||
if (noteNumber <= 0 || noteNumber > notesCount) {
|
||||
throw new NoteIndexOutOfBoundsException("Given number of note is out of range");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
public interface NoteConverter {
|
||||
String convertNoteToString(int noteNumber, Note note);
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.config.AppSettings;
|
||||
import ru.otus.model.Note;
|
||||
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class NoteConverterImpl implements NoteConverter {
|
||||
private final AppSettings appSettings;
|
||||
|
||||
public NoteConverterImpl(AppSettings appSettings) {
|
||||
this.appSettings = appSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertNoteToString(int noteNumber, Note note) {
|
||||
var dateTimeFormatter = DateTimeFormatter.ofPattern(appSettings.getDateTimeFormat());
|
||||
return noteNumber + " | " + dateTimeFormatter.format(note.getCreationTime()) + " | " + note.getText();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface NotesService {
|
||||
List<Note> getAll();
|
||||
|
||||
void save(Note note);
|
||||
|
||||
void remove(String id);
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NotesServiceImpl implements NotesService {
|
||||
private final Map<String, Note> notes;
|
||||
|
||||
public NotesServiceImpl() {
|
||||
notes = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Note> getAll() {
|
||||
return notes.values().stream().map(Note::copy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Note note) {
|
||||
notes.put(note.getId(), note);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String id) {
|
||||
notes.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
target/
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>ru.otus</groupId>
|
||||
<artifactId>solution10_ocp_isp</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<junit.jupiter.version>5.8.2</junit.jupiter.version>
|
||||
<mockito.version>4.1.0</mockito.version>
|
||||
<assertj.version>3.21.0</assertj.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Mockito -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- AssetrtJ -->
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package ru.otus;
|
||||
|
||||
import ru.otus.config.AppSettings;
|
||||
import ru.otus.services.*;
|
||||
import ru.otus.services.processors.*;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
import ru.otus.services.menu.MenuOptionsRegistryImpl;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// OCP + ISP (AppSettings + IOService) + тесты
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
var appSettings = new AppSettings(true, "dd.mm.YYYY HH:mm:ss");
|
||||
var ioService = new IOServiceStreams(System.out, System.in);
|
||||
var applicationStopService = new ApplicationStopServiceImpl(ioService, appSettings);
|
||||
var notesService = new NotesServiceImpl();
|
||||
var noteConverter = new NoteConverterImpl(appSettings);
|
||||
|
||||
var menuOptions = List.of(
|
||||
new MenuOption(1, "Вывести все заметки"),
|
||||
new MenuOption(2, "Добавить заметку"),
|
||||
new MenuOption(3, "Изменить заметку"),
|
||||
new MenuOption(4, "Удалить заметку"),
|
||||
new MenuOption(5, "Выйти")
|
||||
|
||||
);
|
||||
var menuOptionsRegistry = new MenuOptionsRegistryImpl(menuOptions);
|
||||
|
||||
var processors = List.of(
|
||||
new ShowAllNotesSingleCommandProcessor(ioService, notesService, noteConverter, menuOptions.get(0)),
|
||||
new AddNewNoteSingleCommandProcessor(ioService, notesService, menuOptions.get(1)),
|
||||
new UpdateNoteSingleCommandProcessor(ioService, notesService, menuOptions.get(2)),
|
||||
new DeleteNoteSingleCommandProcessor(ioService, notesService, menuOptions.get(3)),
|
||||
new StopApplicationSingleCommandProcessor(applicationStopService, menuOptions.get(4))
|
||||
);
|
||||
|
||||
var menuCommandsProcessor = new MenuCommandsProcessorImpl(processors);
|
||||
|
||||
new ApplicationRunner(ioService, applicationStopService, menuOptionsRegistry, menuCommandsProcessor)
|
||||
.run();
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package ru.otus.config;
|
||||
|
||||
public class AppSettings implements DateTimeFormatProvider, ApplicationStopServiceSettingsProvider{
|
||||
private final boolean confirmExit;
|
||||
private final String dateTimeFormat;
|
||||
|
||||
public AppSettings(boolean confirmExit, String dateTimeFormat) {
|
||||
this.confirmExit = confirmExit;
|
||||
this.dateTimeFormat = dateTimeFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfirmExit() {
|
||||
return confirmExit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDateTimeFormat() {
|
||||
return dateTimeFormat;
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ru.otus.config;
|
||||
|
||||
public interface ApplicationStopServiceSettingsProvider {
|
||||
boolean isConfirmExit();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ru.otus.config;
|
||||
|
||||
public interface DateTimeFormatProvider {
|
||||
String getDateTimeFormat();
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class MenuCommandProcessorNotFound extends RuntimeException {
|
||||
public MenuCommandProcessorNotFound(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class MenuItemIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public MenuItemIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.exceptions;
|
||||
|
||||
public class NoteIndexOutOfBoundsException extends IndexOutOfBoundsException {
|
||||
public NoteIndexOutOfBoundsException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package ru.otus.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Note {
|
||||
private final String id;
|
||||
private final LocalDateTime creationTime;
|
||||
private final String text;
|
||||
|
||||
public Note(String text) {
|
||||
this.id = UUID.randomUUID().toString();
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Note(String id, String text) {
|
||||
this.id = id;
|
||||
this.creationTime = LocalDateTime.now();
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Note(String id, LocalDateTime creationTime, String text) {
|
||||
this.id = id;
|
||||
this.creationTime = creationTime;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public static Note of(String text) {
|
||||
return new Note(text);
|
||||
}
|
||||
|
||||
public static Note of(String id, String text) {
|
||||
return new Note(id, text);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
public Note copy() {
|
||||
return new Note(id, creationTime, text);
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.exceptions.MenuCommandProcessorNotFound;
|
||||
import ru.otus.exceptions.MenuItemIndexOutOfBoundsException;
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
import ru.otus.services.menu.MenuOptionsRegistry;
|
||||
import ru.otus.services.processors.MenuCommandsProcessor;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ApplicationRunner {
|
||||
private final IOService ioService;
|
||||
private final ApplicationStopService applicationStopService;
|
||||
private final MenuOptionsRegistry menuOptionsRegistry;
|
||||
private final MenuCommandsProcessor commandsProcessor;
|
||||
|
||||
|
||||
public ApplicationRunner(IOService ioService,
|
||||
ApplicationStopService applicationStopService,
|
||||
MenuOptionsRegistry menuOptionsRegistry,
|
||||
MenuCommandsProcessor commandsProcessor) {
|
||||
this.ioService = ioService;
|
||||
this.applicationStopService = applicationStopService;
|
||||
this.menuOptionsRegistry = menuOptionsRegistry;
|
||||
this.commandsProcessor = commandsProcessor;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (applicationStopService.isApplicationRunning()) {
|
||||
outputMenu();
|
||||
try {
|
||||
var selectedMenuItem = readSelectedOptionNumber();
|
||||
processMenuCommand(selectedMenuItem);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
ioService.outputString("Ошибка при вводе числа");
|
||||
} catch (MenuItemIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен неверный номер опции");
|
||||
} catch (NoteIndexOutOfBoundsException e) {
|
||||
ioService.outputString("Введен несуществующий номер заметки");
|
||||
} catch (MenuCommandProcessorNotFound e) {
|
||||
ioService.outputString("Не найден обработчик для выбранного пункта меню");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void outputMenu() {
|
||||
ioService.outputString("Выберите одно из следующих действий...");
|
||||
menuOptionsRegistry.getAvailableMenuOptions().stream()
|
||||
.sorted(Comparator.comparingInt(MenuOption::getId))
|
||||
.map(m -> m.getId() + ". " + m.getDescription())
|
||||
.forEach(ioService::outputString);
|
||||
}
|
||||
|
||||
private void processMenuCommand(int selectedMenuItemId) {
|
||||
var selectedMenuOption = menuOptionsRegistry.getMenuOptionById(selectedMenuItemId)
|
||||
.orElseThrow(() -> new MenuItemIndexOutOfBoundsException("Given menu item index is out of range"));
|
||||
|
||||
commandsProcessor.processMenuCommand(selectedMenuOption);
|
||||
}
|
||||
|
||||
private int readSelectedOptionNumber() {
|
||||
return ioService.readInt();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package ru.otus.services;
|
||||
|
||||
public interface ApplicationStopService {
|
||||
boolean isApplicationRunning();
|
||||
void stopApplication();
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.config.ApplicationStopServiceSettingsProvider;
|
||||
import ru.otus.services.processors.InputService;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ApplicationStopServiceImpl implements ApplicationStopService {
|
||||
|
||||
private final InputService inputService;
|
||||
private final ApplicationStopServiceSettingsProvider settingsProvider;
|
||||
private final AtomicBoolean executionFlag;
|
||||
|
||||
public ApplicationStopServiceImpl(InputService inputService,
|
||||
ApplicationStopServiceSettingsProvider settingsProvider) {
|
||||
this.inputService = inputService;
|
||||
this.settingsProvider = settingsProvider;
|
||||
this.executionFlag = new AtomicBoolean(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicationRunning() {
|
||||
return executionFlag.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopApplication() {
|
||||
if (settingsProvider.isConfirmExit()) {
|
||||
var exitConfirmation = inputService.readStringWithPrompt("Действительно выйти? (да/нет)");
|
||||
if (exitConfirmation.equalsIgnoreCase("нет")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
executionFlag.set(false);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.services.processors.InputService;
|
||||
import ru.otus.services.processors.OutputService;
|
||||
|
||||
public interface IOService extends InputService, OutputService {
|
||||
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class IOServiceStreams implements IOService {
|
||||
private final PrintStream output;
|
||||
private final Scanner input;
|
||||
|
||||
public IOServiceStreams(PrintStream outputStream, InputStream inputStream) {
|
||||
output = outputStream;
|
||||
input = new Scanner(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outputString(String s){
|
||||
output.println(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt(){
|
||||
return Integer.parseInt(input.nextLine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readIntWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return Integer.parseInt(input.nextLine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readStringWithPrompt(String prompt){
|
||||
outputString(prompt);
|
||||
return input.nextLine();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
public interface NoteConverter {
|
||||
String convertNoteToString(int noteNumber, Note note);
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.config.DateTimeFormatProvider;
|
||||
import ru.otus.model.Note;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class NoteConverterImpl implements NoteConverter {
|
||||
private final DateTimeFormatProvider dateTimeFormatProvider;
|
||||
|
||||
public NoteConverterImpl(DateTimeFormatProvider dateTimeFormatProvider) {
|
||||
this.dateTimeFormatProvider = dateTimeFormatProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertNoteToString(int noteNumber, Note note) {
|
||||
var dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormatProvider.getDateTimeFormat());
|
||||
return noteNumber + " | " + dateTimeFormatter.format(note.getCreationTime()) + " | " + note.getText();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface NotesService {
|
||||
List<Note> getAll();
|
||||
|
||||
void save(Note note);
|
||||
|
||||
void remove(String id);
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NotesServiceImpl implements NotesService {
|
||||
private final Map<String, Note> notes;
|
||||
|
||||
public NotesServiceImpl() {
|
||||
notes = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Note> getAll() {
|
||||
return notes.values().stream().map(Note::copy).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Note note) {
|
||||
notes.put(note.getId(), note);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String id) {
|
||||
notes.remove(id);
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package ru.otus.services.menu;
|
||||
|
||||
public class MenuOption {
|
||||
private final int id;
|
||||
private final String description;
|
||||
|
||||
public MenuOption(int id, String description) {
|
||||
this.id = id;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
MenuOption that = (MenuOption) o;
|
||||
|
||||
return id == that.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package ru.otus.services.menu;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface MenuOptionsRegistry {
|
||||
List<MenuOption> getAvailableMenuOptions();
|
||||
Optional<MenuOption> getMenuOptionById(int id);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package ru.otus.services.menu;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MenuOptionsRegistryImpl implements MenuOptionsRegistry {
|
||||
private final Map<Integer, MenuOption> options;
|
||||
|
||||
public MenuOptionsRegistryImpl(List<MenuOption> options) {
|
||||
this.options = options.stream()
|
||||
.collect(Collectors.toUnmodifiableMap(MenuOption::getId, Function.identity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuOption> getAvailableMenuOptions() {
|
||||
return options.values().stream().collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MenuOption> getMenuOptionById(int id) {
|
||||
return Optional.ofNullable(options.get(id));
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
import ru.otus.services.NotesService;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
public class AddNewNoteSingleCommandProcessor implements MenuSingleCommandProcessor {
|
||||
private final MenuOption processedCommandOption;
|
||||
private final InputService inputService;
|
||||
private final NotesService notesService;
|
||||
|
||||
public AddNewNoteSingleCommandProcessor(InputService inputService, NotesService notesService,
|
||||
MenuOption processedCommandOption) {
|
||||
this.inputService = inputService;
|
||||
this.notesService = notesService;
|
||||
this.processedCommandOption = processedCommandOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand() {
|
||||
var noteText = inputService.readStringWithPrompt("Введите текст заметки...");
|
||||
notesService.save(Note.of(noteText));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuOption getProcessedCommandOption() {
|
||||
return processedCommandOption;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.services.NotesService;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
|
||||
import static ru.otus.services.processors.utils.NotesListUtil.checkNoteNumber;
|
||||
|
||||
public class DeleteNoteSingleCommandProcessor implements MenuSingleCommandProcessor {
|
||||
private final MenuOption processedCommandOption;
|
||||
private final InputService inputService;
|
||||
private final NotesService notesService;
|
||||
|
||||
public DeleteNoteSingleCommandProcessor(InputService inputService, NotesService notesService,
|
||||
MenuOption processedCommandOption) {
|
||||
this.inputService = inputService;
|
||||
this.notesService = notesService;
|
||||
this.processedCommandOption = processedCommandOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand() {
|
||||
var notes = notesService.getAll();
|
||||
|
||||
var deletedNoteNumber = inputService.readIntWithPrompt("Введите номер удаляемой заметки...");
|
||||
checkNoteNumber(deletedNoteNumber, notes.size());
|
||||
|
||||
var updatedNote = notes.get(deletedNoteNumber - 1);
|
||||
notesService.remove(updatedNote.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuOption getProcessedCommandOption() {
|
||||
return processedCommandOption;
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
public interface InputService {
|
||||
int readInt();
|
||||
|
||||
int readIntWithPrompt(String prompt);
|
||||
|
||||
String readStringWithPrompt(String prompt);
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
public interface MenuCommandsProcessor {
|
||||
void processMenuCommand(MenuOption selectedMenuOption);
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.exceptions.MenuCommandProcessorNotFound;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MenuCommandsProcessorImpl implements MenuCommandsProcessor {
|
||||
private final Map<MenuOption, MenuSingleCommandProcessor> processors;
|
||||
|
||||
public MenuCommandsProcessorImpl(List<MenuSingleCommandProcessor> processors) {
|
||||
this.processors = processors.stream()
|
||||
.collect(Collectors.toMap(MenuSingleCommandProcessor::getProcessedCommandOption, Function.identity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMenuCommand(MenuOption selectedMenuOption) {
|
||||
var commandProcessor = processors.get(selectedMenuOption);
|
||||
if (commandProcessor == null) {
|
||||
throw new MenuCommandProcessorNotFound("Menu command processor for given option does not registered");
|
||||
}
|
||||
commandProcessor.processCommand();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
public interface MenuSingleCommandProcessor {
|
||||
void processCommand();
|
||||
MenuOption getProcessedCommandOption();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
public interface OutputService {
|
||||
void outputString(String s);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.services.NoteConverter;
|
||||
import ru.otus.services.NotesService;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ShowAllNotesSingleCommandProcessor implements MenuSingleCommandProcessor {
|
||||
private final MenuOption processedCommandOption;
|
||||
|
||||
private final OutputService outputService;
|
||||
private final NotesService notesService;
|
||||
private final NoteConverter noteConverter;
|
||||
|
||||
public ShowAllNotesSingleCommandProcessor(OutputService outputService, NotesService notesService,
|
||||
NoteConverter noteConverter, MenuOption processedCommandOption) {
|
||||
this.outputService = outputService;
|
||||
this.notesService = notesService;
|
||||
this.noteConverter = noteConverter;
|
||||
this.processedCommandOption = processedCommandOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand() {
|
||||
var notes = notesService.getAll();
|
||||
outputService.outputString("Заметки:");
|
||||
IntStream.range(1, notes.size() + 1)
|
||||
.mapToObj(k -> noteConverter.convertNoteToString(k, notes.get(k - 1)))
|
||||
.forEach(outputService::outputString);
|
||||
outputService.outputString("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuOption getProcessedCommandOption() {
|
||||
return processedCommandOption;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.services.ApplicationStopService;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
public class StopApplicationSingleCommandProcessor implements MenuSingleCommandProcessor {
|
||||
private final MenuOption processedCommandOption;
|
||||
private final ApplicationStopService applicationStopService;
|
||||
|
||||
public StopApplicationSingleCommandProcessor(ApplicationStopService applicationStopService,
|
||||
MenuOption processedCommandOption) {
|
||||
this.applicationStopService = applicationStopService;
|
||||
this.processedCommandOption = processedCommandOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand() {
|
||||
applicationStopService.stopApplication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuOption getProcessedCommandOption() {
|
||||
return processedCommandOption;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import ru.otus.model.Note;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
import ru.otus.services.NotesService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static ru.otus.services.processors.utils.NotesListUtil.checkNoteNumber;
|
||||
|
||||
public class UpdateNoteSingleCommandProcessor implements MenuSingleCommandProcessor {
|
||||
private final MenuOption processedCommandOption;
|
||||
private final InputService inputService;
|
||||
private final NotesService notesService;
|
||||
|
||||
public UpdateNoteSingleCommandProcessor(InputService inputService, NotesService notesService,
|
||||
MenuOption processedCommandOption) {
|
||||
this.inputService = inputService;
|
||||
this.notesService = notesService;
|
||||
this.processedCommandOption = processedCommandOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand() {
|
||||
var notes = notesService.getAll();
|
||||
|
||||
var updatedNoteNumber = inputService.readIntWithPrompt("Введите номер изменяемой заметки...");
|
||||
checkNoteNumber(updatedNoteNumber, notes.size());
|
||||
|
||||
var noteText = inputService.readStringWithPrompt("Введите текст заметки...");
|
||||
|
||||
var updatedNote = notes.get(updatedNoteNumber - 1);
|
||||
notesService.save(Note.of(updatedNote.getId(), noteText)); }
|
||||
|
||||
@Override
|
||||
public MenuOption getProcessedCommandOption() {
|
||||
return processedCommandOption;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package ru.otus.services.processors.utils;
|
||||
|
||||
import ru.otus.exceptions.NoteIndexOutOfBoundsException;
|
||||
|
||||
public class NotesListUtil {
|
||||
public static void checkNoteNumber(int noteNumber, int notesCount) {
|
||||
if (noteNumber <= 0 || noteNumber > notesCount) {
|
||||
throw new NoteIndexOutOfBoundsException("Given number of note is out of range");
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package ru.otus.services;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import ru.otus.config.ApplicationStopServiceSettingsProvider;
|
||||
import ru.otus.services.processors.InputService;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@DisplayName("Сервис остановки приложения ")
|
||||
class ApplicationStopServiceImplTest {
|
||||
|
||||
@DisplayName("должен возвращать корректный статус работы приложения")
|
||||
@ParameterizedTest(name = "остановить приложение: {0}, ожидаемый результат: {1}")
|
||||
@CsvSource({"false, true", "true, false"})
|
||||
void shouldReturnCorrectApplicationExecutionStatus(boolean shouldStopApplication, boolean expectedStatus) {
|
||||
var inputService = mock(InputService.class);
|
||||
var settingsProvider = mock(ApplicationStopServiceSettingsProvider.class);
|
||||
given(settingsProvider.isConfirmExit()).willReturn(false);
|
||||
var applicationStopService = new ApplicationStopServiceImpl(inputService, settingsProvider);
|
||||
|
||||
if (shouldStopApplication) {
|
||||
applicationStopService.stopApplication();
|
||||
verify(settingsProvider, times(1)).isConfirmExit();
|
||||
}
|
||||
var actualStatus = applicationStopService.isApplicationRunning();
|
||||
assertThat(actualStatus).isEqualTo(expectedStatus);
|
||||
verify(inputService, never()).readStringWithPrompt(any());
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package ru.otus.services.menu;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@DisplayName("Реестр опций меню ")
|
||||
class MenuOptionsRegistryImplTest {
|
||||
|
||||
private List<MenuOption> options;
|
||||
private MenuOptionsRegistryImpl menuOptionsRegistry;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
options = List.of(new MenuOption(1, "opt1"), new MenuOption(2, "opt2"));
|
||||
menuOptionsRegistry = new MenuOptionsRegistryImpl(options);
|
||||
}
|
||||
|
||||
@DisplayName("должен возвращать список ожидаемых опций ")
|
||||
@Test
|
||||
void shouldReturnExpectedAvailableMenuOptions() {
|
||||
var actualOptions = menuOptionsRegistry.getAvailableMenuOptions();
|
||||
assertThat(actualOptions)
|
||||
.usingRecursiveFieldByFieldElementComparator()
|
||||
.containsExactlyInAnyOrderElementsOf(options);
|
||||
}
|
||||
|
||||
@DisplayName("должен корректно возвращать опцию меню по ее идентификатору ")
|
||||
@Test
|
||||
void shouldReturnExpectedMenuOptionById() {
|
||||
var expectedOption = options.get(0);
|
||||
var actualOption = menuOptionsRegistry.getMenuOptionById(expectedOption.getId());
|
||||
assertThat(actualOption).isNotEmpty()
|
||||
.get()
|
||||
.usingRecursiveComparison()
|
||||
.isEqualTo(expectedOption);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import ru.otus.model.Note;
|
||||
import ru.otus.services.NotesService;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@DisplayName("Процессор команды добавления новой заметки ")
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class AddNewNoteSingleCommandProcessorTest {
|
||||
|
||||
@Mock
|
||||
private MenuOption processedCommandOption;
|
||||
|
||||
@Mock
|
||||
private InputService inputService;
|
||||
|
||||
@Mock
|
||||
private NotesService notesService;
|
||||
|
||||
@InjectMocks
|
||||
private AddNewNoteSingleCommandProcessor processor;
|
||||
|
||||
@DisplayName("должен корректно добавлять новой заметки ")
|
||||
@Test
|
||||
void shouldCorrectAddExpectedNoteUseExpectedServicesMethods() {
|
||||
var expectedNoteText = "Expected Note Text";
|
||||
given(inputService.readStringWithPrompt(anyString()))
|
||||
.willReturn(expectedNoteText);
|
||||
|
||||
processor.processCommand();
|
||||
|
||||
verify(inputService, times(1)).readStringWithPrompt(any());
|
||||
|
||||
var captor = ArgumentCaptor.forClass(Note.class);
|
||||
verify(notesService).save(captor.capture());
|
||||
var actualNote = captor.getValue();
|
||||
assertThat(actualNote).extracting(Note::getText).isEqualTo(expectedNoteText);
|
||||
|
||||
}
|
||||
|
||||
@DisplayName("должен возвращает ожидаемый тип обрабатываемой команды")
|
||||
@Test
|
||||
void shouldReturnExpectedProcessedCommandOption() {
|
||||
assertThat(processor.getProcessedCommandOption()).isEqualTo(processedCommandOption);
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package ru.otus.services.processors;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import ru.otus.exceptions.MenuCommandProcessorNotFound;
|
||||
import ru.otus.services.menu.MenuOption;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@DisplayName("Процессор команд меню ")
|
||||
class MenuCommandsProcessorImplTest {
|
||||
|
||||
private List<MenuSingleCommandProcessor> singleCommandProcessors;
|
||||
private MenuCommandsProcessorImpl processor;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
singleCommandProcessors = new ArrayList<>(3);
|
||||
for (int i = 1; i < 4; i++) {
|
||||
var opt = new MenuOption(i, "opt" + i);
|
||||
var singleCommandProcessor = mock(MenuSingleCommandProcessor.class);
|
||||
given(singleCommandProcessor.getProcessedCommandOption()).willReturn(opt);
|
||||
singleCommandProcessors.add(singleCommandProcessor);
|
||||
}
|
||||
processor = new MenuCommandsProcessorImpl(singleCommandProcessors);
|
||||
}
|
||||
|
||||
@DisplayName("должен корректно обрабатывать команду если для нее есть процессор")
|
||||
@Test
|
||||
void shouldCorrectProcessMenuCommandWhenProcessorForGivenCommandExists() {
|
||||
for (var singleCommandProcessor: singleCommandProcessors) {
|
||||
processor.processMenuCommand(singleCommandProcessor.getProcessedCommandOption());
|
||||
verify(singleCommandProcessor, times(1)).processCommand();
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("должен кидать ожидаемое исключение если процессор для заданной команды отсутствует")
|
||||
@Test
|
||||
void shouldThrowExpectedExceptionWhenProcessorForGivenCommandDoesNotExists() {
|
||||
var commandOptionWithNotExistingProcessor = new MenuOption(4, "opt4");
|
||||
assertThatCode(() -> processor.processMenuCommand(commandOptionWithNotExistingProcessor))
|
||||
.isInstanceOf(MenuCommandProcessorNotFound.class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user