mirror of
https://github.com/OtusTeam/Spring.git
synced 2026-05-30 10:50:42 +00:00
hw02-annotation-config template added
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
target/
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
### 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,112 @@
|
||||
<?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.hw</groupId>
|
||||
<artifactId>hw02-annotation-config</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring.version>6.0.12</spring.version>
|
||||
<opencsv.version>5.8</opencsv.version>
|
||||
<junit.version>5.10.0</junit.version>
|
||||
<mockito.version>5.4.0</mockito.version>
|
||||
<assertj.version>3.24.2</assertj.version>
|
||||
<lombok.version>1.18.28</lombok.version>
|
||||
<checkstyle-plugin.version>3.2.2</checkstyle-plugin.version>
|
||||
<checkstyle.version>10.11.0</checkstyle.version>
|
||||
<checkstyle.config.url>
|
||||
https://raw.githubusercontent.com/OtusTeam/Spring/master/checkstyle.xml
|
||||
</checkstyle.config.url>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>${opencsv.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${mockito.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${assertj.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${checkstyle-plugin.version}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>${checkstyle.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<configLocation>${checkstyle.config.url}</configLocation>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<!--Настроить для создания jar с зависимостями-->
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package ru.otus.hw;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import ru.otus.hw.service.TestRunnerService;
|
||||
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
|
||||
//Создать контекст на основе Annotation/Java конфигурирования
|
||||
ApplicationContext context = null;
|
||||
var testRunnerService = context.getBean(TestRunnerService.class);
|
||||
testRunnerService.run();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package ru.otus.hw.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
public class AppConfig implements TestConfig, TestFileNameProvider {
|
||||
|
||||
// внедрить свойство из application.properties
|
||||
private int rightAnswersCountToPass;
|
||||
|
||||
// внедрить свойство из application.properties
|
||||
private String testFileName;
|
||||
|
||||
@Override
|
||||
public int getRightAnswersCountToPass() {
|
||||
return rightAnswersCountToPass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTestFileName() {
|
||||
return testFileName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ru.otus.hw.config;
|
||||
|
||||
public interface TestConfig {
|
||||
int getRightAnswersCountToPass();
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ru.otus.hw.config;
|
||||
|
||||
public interface TestFileNameProvider {
|
||||
String getTestFileName();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package ru.otus.hw.dao;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import ru.otus.hw.config.TestFileNameProvider;
|
||||
import ru.otus.hw.domain.Question;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class CsvQuestionDao implements QuestionDao {
|
||||
private final TestFileNameProvider fileNameProvider;
|
||||
|
||||
@Override
|
||||
public List<Question> findAll() {
|
||||
// Использовать CsvToBean
|
||||
// https://opencsv.sourceforge.net/#collection_based_bean_fields_one_to_many_mappings
|
||||
// Использовать QuestionReadException
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package ru.otus.hw.dao;
|
||||
|
||||
import ru.otus.hw.domain.Question;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface QuestionDao {
|
||||
List<Question> findAll();
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package ru.otus.hw.dao.dto;
|
||||
|
||||
import com.opencsv.bean.AbstractCsvConverter;
|
||||
import ru.otus.hw.domain.Answer;
|
||||
|
||||
public class AnswerCsvConverter extends AbstractCsvConverter {
|
||||
|
||||
@Override
|
||||
public Object convertToRead(String value) {
|
||||
var valueArr = value.split("%");
|
||||
return new Answer(valueArr[0], Boolean.parseBoolean(valueArr[1]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package ru.otus.hw.dao.dto;
|
||||
|
||||
import com.opencsv.bean.CsvBindAndSplitByPosition;
|
||||
import com.opencsv.bean.CsvBindByPosition;
|
||||
import lombok.Data;
|
||||
import ru.otus.hw.domain.Answer;
|
||||
import ru.otus.hw.domain.Question;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class QuestionDto {
|
||||
|
||||
@CsvBindByPosition(position = 0)
|
||||
private String text;
|
||||
|
||||
@CsvBindAndSplitByPosition(position = 1, collectionType = ArrayList.class, elementType = Answer.class,
|
||||
converter = AnswerCsvConverter.class, splitOn = "\\|")
|
||||
private List<Answer> answers;
|
||||
|
||||
public Question toDomainObject() {
|
||||
return new Question(text, answers);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package ru.otus.hw.domain;
|
||||
|
||||
public record Answer(String text, boolean isCorrect) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package ru.otus.hw.domain;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record Question(String text, List<Answer> answers) {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ru.otus.hw.domain;
|
||||
|
||||
public record Student(String firstName, String lastName) {
|
||||
public String getFullName() {
|
||||
return String.format("%s %s", firstName, lastName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package ru.otus.hw.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TestResult {
|
||||
private final Student student;
|
||||
|
||||
private final List<Question> answeredQuestions;
|
||||
|
||||
private int rightAnswersCount;
|
||||
|
||||
public TestResult(Student student) {
|
||||
this.student = student;
|
||||
this.answeredQuestions = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void applyAnswer(Question question, boolean isRightAnswer) {
|
||||
answeredQuestions.add(question);
|
||||
if (isRightAnswer) {
|
||||
rightAnswersCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ru.otus.hw.exceptions;
|
||||
|
||||
public class QuestionReadException extends RuntimeException {
|
||||
public QuestionReadException(String message, Throwable ex) {
|
||||
super(message, ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
public interface IOService {
|
||||
void printLine(String s);
|
||||
|
||||
void printFormattedLine(String s, Object ...args);
|
||||
|
||||
String readString();
|
||||
|
||||
String readStringWithPrompt(String prompt);
|
||||
|
||||
int readIntForRange(int min, int max, String errorMessage);
|
||||
|
||||
int readIntForRangeWithPrompt(int min, int max, String prompt, String errorMessage);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import ru.otus.hw.domain.TestResult;
|
||||
|
||||
public interface ResultService {
|
||||
void showResult(TestResult testResult);
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import ru.otus.hw.config.TestConfig;
|
||||
import ru.otus.hw.domain.TestResult;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ResultServiceImpl implements ResultService {
|
||||
|
||||
private final TestConfig testConfig;
|
||||
|
||||
private final IOService ioService;
|
||||
|
||||
@Override
|
||||
public void showResult(TestResult testResult) {
|
||||
ioService.printLine("");
|
||||
ioService.printLine("Test results: ");
|
||||
ioService.printFormattedLine("Student: %s", testResult.getStudent().getFullName());
|
||||
ioService.printFormattedLine("Answered questions count: %d", testResult.getAnsweredQuestions().size());
|
||||
ioService.printFormattedLine("Right answers count: %d", testResult.getRightAnswersCount());
|
||||
|
||||
if (testResult.getRightAnswersCount() >= testConfig.getRightAnswersCountToPass()) {
|
||||
ioService.printLine("Congratulations! You passed test!");
|
||||
return;
|
||||
}
|
||||
ioService.printLine("Sorry. You fail test.");
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class StreamsIOService implements IOService {
|
||||
private static final int MAX_ATTEMPTS = 10;
|
||||
|
||||
private final PrintStream printStream;
|
||||
|
||||
private final Scanner scanner;
|
||||
|
||||
public StreamsIOService(@Value("#{T(System).out}") PrintStream printStream,
|
||||
@Value("#{T(System).in}") InputStream inputStream) {
|
||||
|
||||
this.printStream = printStream;
|
||||
this.scanner = new Scanner(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printLine(String s) {
|
||||
printStream.println(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printFormattedLine(String s, Object... args) {
|
||||
printStream.printf(s + "%n", args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString() {
|
||||
return scanner.nextLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readStringWithPrompt(String prompt) {
|
||||
printLine(prompt);
|
||||
return scanner.nextLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readIntForRange(int min, int max, String errorMessage) {
|
||||
for (int i = 0; i < MAX_ATTEMPTS; i++) {
|
||||
try {
|
||||
var stringValue = scanner.nextLine();
|
||||
int intValue = Integer.parseInt(stringValue);
|
||||
if (intValue < min || intValue > max) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return intValue;
|
||||
} catch (IllegalArgumentException e) {
|
||||
printLine(errorMessage);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Error during reading int value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readIntForRangeWithPrompt(int min, int max, String prompt, String errorMessage) {
|
||||
printLine(prompt);
|
||||
return readIntForRange(min, max, errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import ru.otus.hw.domain.Student;
|
||||
|
||||
public interface StudentService {
|
||||
|
||||
Student determineCurrentStudent();
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import ru.otus.hw.domain.Student;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class StudentServiceImpl implements StudentService {
|
||||
|
||||
private final IOService ioService;
|
||||
|
||||
@Override
|
||||
public Student determineCurrentStudent() {
|
||||
var firstName = ioService.readStringWithPrompt("Please input your first name");
|
||||
var lastName = ioService.readStringWithPrompt("Please input your last name");
|
||||
return new Student(firstName, lastName);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
public interface TestRunnerService {
|
||||
void run();
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class TestRunnerServiceImpl implements TestRunnerService {
|
||||
|
||||
private final TestService testService;
|
||||
|
||||
private final StudentService studentService;
|
||||
|
||||
private final ResultService resultService;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
var student = studentService.determineCurrentStudent();
|
||||
var testResult = testService.executeTestFor(student);
|
||||
resultService.showResult(testResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import ru.otus.hw.domain.Student;
|
||||
import ru.otus.hw.domain.TestResult;
|
||||
|
||||
public interface TestService {
|
||||
TestResult executeTestFor(Student student);
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package ru.otus.hw.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import ru.otus.hw.dao.QuestionDao;
|
||||
import ru.otus.hw.domain.Student;
|
||||
import ru.otus.hw.domain.TestResult;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class TestServiceImpl implements TestService {
|
||||
|
||||
private final IOService ioService;
|
||||
private final QuestionDao questionDao;
|
||||
|
||||
@Override
|
||||
public TestResult executeTestFor(Student student) {
|
||||
ioService.printLine("");
|
||||
ioService.printFormattedLine("Please answer the questions below%n");
|
||||
var questions = questionDao.findAll();
|
||||
var testResult = new TestResult(student);
|
||||
|
||||
for (var question: questions) {
|
||||
var isAnswerValid = false; // Задать вопрос, получить ответ
|
||||
testResult.applyAnswer(question, isAnswerValid);
|
||||
}
|
||||
return testResult;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
test.rightAnswersCountToPass=3
|
||||
test.fileName=questions.csv
|
||||
@@ -0,0 +1,4 @@
|
||||
# Добавить сюда своих вопросов. Эту строку надо пропустить при настройке CsvToBean (withSkipLines)
|
||||
Is there life on Mars?;Science doesn't know this yet%true|Certainly. The red UFO is from Mars. And green is from Venus%false|Absolutely not%false
|
||||
How should resources be loaded form jar in Java?;ClassLoader#geResourceAsStream or ClassPathResource#getInputStream%true|ClassLoader#geResource#getFile + FileReader%false|Wingardium Leviosa%false
|
||||
Which option is a good way to handle the exception?;@SneakyThrow%false|e.printStackTrace()%false|Rethrow with wrapping in business exception (for example, QuestionReadException)%true|Ignoring exception%false
|
||||
|
Reference in New Issue
Block a user