mirror of
https://github.com/OtusTeam/Spring.git
synced 2026-05-30 10:50:42 +00:00
2022-05 - 01
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>
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
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, +ApplicationStopService, IOService стал Streams, методы MenuCommandsProcessor очистились от 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 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>
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
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 showAllNotesMenuOption = new MenuOption(1, "Вывести все заметки");
|
||||||
|
var addNewNoteMenuOption = new MenuOption(2, "Добавить заметку");
|
||||||
|
var updateNoteMenuOption = new MenuOption(3, "Изменить заметку");
|
||||||
|
var deleteNoteMenuOption = new MenuOption(4, "Удалить заметку");
|
||||||
|
var stopApplicationMenuOption = new MenuOption(5, "Выйти");
|
||||||
|
|
||||||
|
var menuOptions = List.of(showAllNotesMenuOption, addNewNoteMenuOption,
|
||||||
|
updateNoteMenuOption, deleteNoteMenuOption, stopApplicationMenuOption
|
||||||
|
);
|
||||||
|
var menuOptionsRegistry = new MenuOptionsRegistryImpl(menuOptions);
|
||||||
|
|
||||||
|
var processors = List.of(
|
||||||
|
new ShowAllNotesSingleCommandProcessor(ioService, notesService, noteConverter, showAllNotesMenuOption),
|
||||||
|
new AddNewNoteSingleCommandProcessor(ioService, notesService, addNewNoteMenuOption),
|
||||||
|
new UpdateNoteSingleCommandProcessor(ioService, notesService, updateNoteMenuOption),
|
||||||
|
new DeleteNoteSingleCommandProcessor(ioService, notesService, deleteNoteMenuOption),
|
||||||
|
new StopApplicationSingleCommandProcessor(applicationStopService, stopApplicationMenuOption)
|
||||||
|
);
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обратить внимание на работу с Optional
|
||||||
|
@DisplayName("должен корректно возвращать опцию меню по ее идентификатору ")
|
||||||
|
@Test
|
||||||
|
void shouldReturnExpectedMenuOptionById() {
|
||||||
|
var expectedOption = options.get(0);
|
||||||
|
var actualOption = menuOptionsRegistry.getMenuOptionById(expectedOption.getId());
|
||||||
|
assertThat(actualOption).isNotEmpty()
|
||||||
|
.get()
|
||||||
|
.usingRecursiveComparison()
|
||||||
|
.isEqualTo(expectedOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/build/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?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>spring-01</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>spring-01-exercise</module>
|
||||||
|
<module>spring-01-solution</module>
|
||||||
|
</modules>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?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>spring-01-exercise</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>
|
||||||
|
<!-- TODO: Добавьте зависимость spring-context -->
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package ru.otus.spring;
|
||||||
|
|
||||||
|
//import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
import ru.otus.spring.domain.Person;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// TODO: создайте здесь класс контекста
|
||||||
|
|
||||||
|
// TODO: Получите Person Service
|
||||||
|
|
||||||
|
// Получите Person "Ivan"
|
||||||
|
Person ivan = null;
|
||||||
|
System.out.println("name: " + ivan.getName() + " age: " + ivan.getAge());
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user