diff --git a/pom.xml b/pom.xml index b593796e496d9680d1416be0ca5a1ad2619ab19a..ec1d0f05e6ecdea0a278eb5468cf39cf1e347767 100644 --- a/pom.xml +++ b/pom.xml @@ -3,10 +3,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cz.vsb.fei.java2</groupId> - <artifactId>java2-lab04-v3</artifactId> + <artifactId>java2-lab05-v3</artifactId> <version>0.0.1-SNAPHOST</version> <packaging>jar</packaging> - <name>java2-lab04-v3</name> + <name>java2-lab05-v3</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>21</maven.compiler.source> @@ -57,7 +57,6 @@ <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.3.232</version> - <scope>runtime</scope> </dependency> <dependency> diff --git a/src/main/java/lab/Setup.java b/src/main/java/lab/Setup.java index 9f5e5eddf563503b38f83f0fe2ca3ceebb374f07..d1f4b9ec802d4a3deacc74787fd0b8d5370ec52e 100644 --- a/src/main/java/lab/Setup.java +++ b/src/main/java/lab/Setup.java @@ -3,12 +3,17 @@ package lab; import lab.storage.DbConnector; import lab.storage.ScoreStorageInterface; import lombok.AllArgsConstructor; -import lombok.Getter; +import lombok.Builder; import lombok.Builder.Default; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; @Getter @AllArgsConstructor -@lombok.Builder(toBuilder = true) +@EqualsAndHashCode +@ToString +@Builder(toBuilder = true) public class Setup { @Getter diff --git a/src/main/java/lab/data/Level.java b/src/main/java/lab/data/Level.java new file mode 100644 index 0000000000000000000000000000000000000000..4c8e6bdc522cf341b1a20515853f8f019484998d --- /dev/null +++ b/src/main/java/lab/data/Level.java @@ -0,0 +1,5 @@ +package lab.data; + +public enum Level { + EASY, MEDIUM, HARD; +} diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java index 71011021a0d6dabdb1ead49426440dab6cbd8797..247a9b4442f21b7cb6e894e98de691f5c81c5edc 100644 --- a/src/main/java/lab/data/Score.java +++ b/src/main/java/lab/data/Score.java @@ -3,6 +3,7 @@ package lab.data; import java.util.Random; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -13,15 +14,19 @@ import lombok.ToString; @AllArgsConstructor @EqualsAndHashCode @ToString +@Builder(toBuilder = true) public class Score { private static final Random RANDOM = new Random(); + private Long id; private String name; private int points; + private Level level; + public static Score generate() { - return new Score(getRandomNick(), RANDOM.nextInt(50, 300)); + return new Score(null, getRandomNick(), RANDOM.nextInt(50, 300), Level.values()[RANDOM.nextInt(Level.values().length)]); } public static final String[] nicks = { "CyberSurfer", "PixelPioneer", "SocialSavvy", "DigitalDynamo", "ByteBuddy", "InstaGuru", @@ -46,4 +51,4 @@ public class Score { return nicks[RANDOM.nextInt(nicks.length)]; } -} +} \ No newline at end of file diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index ec45080c6b280cd4e006d86c31bb7b1402b3538e..cb62b5f56144f51c2767263737e667daf9bbd68e 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -6,6 +6,7 @@ import java.sql.SQLException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.h2.tools.Server; import javafx.application.Application; import javafx.fxml.FXMLLoader; @@ -14,6 +15,7 @@ import javafx.scene.Scene; import javafx.stage.Stage; import javafx.stage.WindowEvent; import lab.Setup; +import lab.storage.JpaConnector; /** * Class <b>App</b> - extends class Application and it is an entry point of the @@ -30,10 +32,24 @@ public class App extends Application { public static void main(String[] args) { log.info("Application lauched"); - Setup.configure(Setup.getInstanceForHardcoreGame().toBuilder().boatHitPulseX(-20).build()); + Setup.configure(Setup.builder().scoreStorageInterface(new JpaConnector()).build()); + + startH2WebServerToInspectDb(); + launch(args); } + private static void startH2WebServerToInspectDb() { + //Start HTTP server for access H2 DB for look inside + try { + Server server = Server.createWebServer(); + log.info(server.getURL()); + server.start(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Override public void start(Stage primaryStage) { try { @@ -84,6 +100,7 @@ public class App extends Application { if(gameController != null) { gameController.stop(); } + Setup.getInstance().getScoreStorageInterface().stop(); log.info("Exiting game"); System.exit(0); } diff --git a/src/main/java/lab/gui/GameController.java b/src/main/java/lab/gui/GameController.java index 9bf7eceac68170a83783a98afedfc90cb3153247..0b059c10acf652e05779b089cbe472fb9c00fb8f 100644 --- a/src/main/java/lab/gui/GameController.java +++ b/src/main/java/lab/gui/GameController.java @@ -1,7 +1,5 @@ package lab.gui; -import java.util.List; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -10,13 +8,8 @@ import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.canvas.Canvas; -import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Slider; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; -import lab.Setup; -import lab.data.Score; import lab.game.DrawingThread; import lab.game.LochNess; import lab.game.Scene; @@ -27,24 +20,6 @@ public class GameController { private Scene scene; - @FXML - private Button btnGenerateScore; - - @FXML - private Button btnLoadAll; - - @FXML - private Button btnLoadFirstTen; - - @FXML - private TableView<Score> scores; - - @FXML - private TableColumn<Score, String> nickColumn; - - @FXML - private TableColumn<Score, Integer> pointsColumn; - @FXML private Slider boatPosition; @@ -79,28 +54,6 @@ public class GameController { playerName.setText(String.format("Number of dead lochnesses: %03d", deadLochNessCounter)); } - @FXML - void btnGenerateScoreAction(ActionEvent event) { - Score score = Score.generate(); - this.scores.getItems().add(score); - Setup.getInstance().getScoreStorageInterface().insertScore(score); - } - - @FXML - void btnLoadAllAction(ActionEvent event) { - updateScoreTable(Setup.getInstance().getScoreStorageInterface().getAll()); - } - - @FXML - void btnLoadFirstTenAction(ActionEvent event) { - updateScoreTable(Setup.getInstance().getScoreStorageInterface().getFirstTen()); - } - - private void updateScoreTable(List<Score> scores) { - this.scores.getItems().clear(); - this.scores.getItems().addAll(scores); - } - @FXML void initialize() { assert boatPosition != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'."; diff --git a/src/main/java/lab/gui/MainScreenController.java b/src/main/java/lab/gui/MainScreenController.java index 8ac4454f1c823e1a32850dffc33bee8d806ed1a9..07d483b025f89473b3c8b282d89c33a9aaab87cd 100644 --- a/src/main/java/lab/gui/MainScreenController.java +++ b/src/main/java/lab/gui/MainScreenController.java @@ -1,14 +1,17 @@ package lab.gui; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import javafx.collections.ListChangeListener; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; +import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextField; @@ -35,6 +38,10 @@ public class MainScreenController { @FXML private Button btnLoadFirstTen; + @FXML + private Button btnDelete; + + @FXML private TableView<Score> scores; @@ -44,6 +51,9 @@ public class MainScreenController { @FXML private TableColumn<Score, Integer> pointsColumn; + @FXML + private TableColumn<Score, Integer> difficultColumn; + @FXML private ToggleGroup difficult; @@ -75,7 +85,7 @@ public class MainScreenController { void btnGenerateScoreAction(ActionEvent event) { Score score = Score.generate(); this.scores.getItems().add(score); - Setup.getInstance().getScoreStorageInterface().insertScore(score); + Setup.getInstance().getScoreStorageInterface().save(score); } @FXML @@ -87,6 +97,13 @@ public class MainScreenController { void btnLoadFirstTenAction(ActionEvent event) { updateScoreTable(Setup.getInstance().getScoreStorageInterface().getFirstTen()); } + + @FXML + void btnDeleteAction(ActionEvent event) { + List<Score> selectedScores = new ArrayList<>(scores.getSelectionModel().getSelectedItems()); + Setup.getInstance().getScoreStorageInterface().delete(selectedScores); + updateScoreTable(Setup.getInstance().getScoreStorageInterface().getAll()); + } private void updateScoreTable(List<Score> scores) { this.scores.getItems().clear(); @@ -103,12 +120,19 @@ public class MainScreenController { nickColumn.setCellValueFactory(new PropertyValueFactory<>("name")); pointsColumn.setCellValueFactory(new PropertyValueFactory<>("points")); + difficultColumn.setCellValueFactory(new PropertyValueFactory<>("level")); + + btnDelete.setDisable(true); + scores.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + scores.getSelectionModel().getSelectedItems() + .addListener((ListChangeListener.Change<? extends Score> change) -> + btnDelete.setDisable(change.getList().isEmpty())); - initDB(); + initStorage(); log.info("Screeen initialized."); } - private void initDB() { + private void initStorage() { Setup.getInstance().getScoreStorageInterface().init(); scores.getItems().addAll(Setup.getInstance().getScoreStorageInterface().getAll()); } diff --git a/src/main/java/lab/storage/DbConnector.java b/src/main/java/lab/storage/DbConnector.java index f20e88bc194bbb6ad2ac7ad33f4def5d5504e7dc..4b1e19084c83c05b136ef332e9addf755eb2b7b8 100644 --- a/src/main/java/lab/storage/DbConnector.java +++ b/src/main/java/lab/storage/DbConnector.java @@ -9,16 +9,10 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import lab.data.Score; - public class DbConnector implements ScoreStorageInterface { - private static Logger log = LogManager.getLogger(DbConnector.class); - private static final String JDBC_CONECTIN_STRING = "jdbc:h2:file:./scoreDB"; @Override @@ -37,7 +31,7 @@ public class DbConnector implements ScoreStorageInterface { Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery(query);) { while (rs.next()) { - result.add(new Score(rs.getString("nick"), rs.getInt("points"))); + result.add(new Score(null, rs.getString("nick"), rs.getInt("points"), null)); } } catch (SQLException e) { e.printStackTrace(); @@ -56,7 +50,7 @@ public class DbConnector implements ScoreStorageInterface { } @Override - public void insertScore(Score score) { + public Score save(Score score) { try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING); PreparedStatement stm = con.prepareStatement("INSERT INTO scores VALUES (?, ?)");) { stm.setString(1, score.getName()); @@ -65,5 +59,26 @@ public class DbConnector implements ScoreStorageInterface { } catch (SQLException e) { e.printStackTrace(); } + return score; + } + + @Override + public void delete(List<Score> scores) { + try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING); + PreparedStatement stm = con.prepareStatement("DELETE FROM scores WHERE nick=? AND points=?");) { + for (Score score : scores) { + stm.setString(1, score.getName()); + stm.setInt(2, score.getPoints()); + stm.executeUpdate(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void stop() { + /*nothing to do*/ } + } diff --git a/src/main/java/lab/storage/FileStorage.java b/src/main/java/lab/storage/FileStorage.java index a3228c16a88a3dccaaecda85b3b38a1eb916f46f..828ca068af9f5b7539ab0dec4c62fedf417d4fc4 100644 --- a/src/main/java/lab/storage/FileStorage.java +++ b/src/main/java/lab/storage/FileStorage.java @@ -21,7 +21,7 @@ public class FileStorage implements ScoreStorageInterface { if (Files.exists(Paths.get(SCORE_FILE_NAME))) { try (Stream<String> lines = Files.lines(Paths.get(SCORE_FILE_NAME))) { List<Score> result = lines.map(line -> line.split(";")) - .map(parts -> new Score(parts[0], Integer.parseInt(parts[1]))).toList(); + .map(parts -> new Score(null, parts[0], Integer.parseInt(parts[1]), null)).toList(); return new ArrayList<>(result); } catch (IOException e) { e.printStackTrace(); @@ -43,14 +43,33 @@ public class FileStorage implements ScoreStorageInterface { } @Override - public void insertScore(Score score) { + public Score save(Score score) { List<Score> all = getAll(); all.add(score); + storeAll(all); + return score; + } + + private void storeAll(List<Score> all) { List<String> lines = all.stream().map(s -> String.format("%s;%d", s.getName(), s.getPoints())).toList(); try { - Files.write(Paths.get(SCORE_FILE_NAME), lines, StandardOpenOption.CREATE); + Files.write(Paths.get(SCORE_FILE_NAME), lines, StandardOpenOption.TRUNCATE_EXISTING); } catch (IOException e) { e.printStackTrace(); } } + + @Override + public void delete(List<Score> scores) { + List<Score> all = getAll(); + all.removeAll(scores); + storeAll(all); + + } + + @Override + public void stop() { + /*nothing to do*/ + } + } diff --git a/src/main/java/lab/storage/JpaConnector.java b/src/main/java/lab/storage/JpaConnector.java new file mode 100644 index 0000000000000000000000000000000000000000..b1f5bf10a6129abf829d8a7283603076b76a2e7d --- /dev/null +++ b/src/main/java/lab/storage/JpaConnector.java @@ -0,0 +1,54 @@ +package lab.storage; + +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +import lab.data.Score; + +public class JpaConnector implements ScoreStorageInterface { + + + public JpaConnector() { + } + + @Override + public List<Score> getAll() { + return Collections.emptyList(); + } + + @Override + public List<Score> getFirstTen() { + return Collections.emptyList(); + } + + @Override + public void init() { + } + + @Override + public Score save(Score score) { + return null; + } + + @Override + public void delete(List<Score> scores) { + } + + @Override + public void stop() { + } + + public Object getEntityManager() { + //return entity manager. Type Object is there because of compilation of empty task assignment + return null; + } + + public Score find(long id) { + return null; + } + + public void modifyNoPersistOrMerge(long id, Consumer<Score> motificator) { + } + +} diff --git a/src/main/java/lab/storage/ScoreStorageInterface.java b/src/main/java/lab/storage/ScoreStorageInterface.java index 67ee80d94e2662312f68642b923a0912aa5ae0fc..af8932ec4fbdf9ba3fe85d9649f2131f02edf461 100644 --- a/src/main/java/lab/storage/ScoreStorageInterface.java +++ b/src/main/java/lab/storage/ScoreStorageInterface.java @@ -12,6 +12,10 @@ public interface ScoreStorageInterface { void init(); - void insertScore(Score score); + Score save(Score score); + + void delete(List<Score> scores); + + void stop(); } \ No newline at end of file diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index cfa87d79b17c05dba67923aa52b2e3aa826eddab..8f97c195abf646bd9ee2909fae4c51d29014984d 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,10 +1,11 @@ -module lab04_module { +module lab05_module { requires transitive javafx.controls; requires javafx.fxml; requires javafx.base; requires java.sql; requires org.apache.logging.log4j; requires static lombok; + requires com.h2database; opens lab.gui to javafx.fxml; opens lab.data to javafx.base; diff --git a/src/main/resources/lab/gui/mainScreen.fxml b/src/main/resources/lab/gui/mainScreen.fxml index 23b69f83632a03fd4a90dd35c089fc443e28c26a..4fc321222250ed3e6d9d2c5ac912f6e4b5653df4 100644 --- a/src/main/resources/lab/gui/mainScreen.fxml +++ b/src/main/resources/lab/gui/mainScreen.fxml @@ -59,6 +59,7 @@ <columns> <TableColumn fx:id="nickColumn" prefWidth="75.0" text="Nick" /> <TableColumn fx:id="pointsColumn" prefWidth="75.0" text="Points" /> + <TableColumn fx:id="difficultColumn" prefWidth="75.0" text="Difficult" /> </columns> <columnResizePolicy> <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> @@ -67,6 +68,7 @@ <Button fx:id="btnGenerateScore" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnGenerateScoreAction" text="Generate new score" /> <Button fx:id="btnLoadAll" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnLoadAllAction" text="Load all from DB" /> <Button fx:id="btnLoadFirstTen" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnLoadFirstTenAction" text="Load first 10 from DB" /> + <Button fx:id="btnDelete" layoutX="10.0" layoutY="312.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnDeleteAction" text="Delete" /> </children> </VBox> </children> diff --git a/src/test/java/jez04/structure/test/ClassStructureTest.java b/src/test/java/jez04/structure/test/ClassStructureTest.java index 95bab29ac292caedc816a27dfe31b203bb856070..21c3023a1e362b7c8191843eee2cbda6fabde061 100644 --- a/src/test/java/jez04/structure/test/ClassStructureTest.java +++ b/src/test/java/jez04/structure/test/ClassStructureTest.java @@ -2,85 +2,176 @@ package jez04.structure.test; import static org.hamcrest.MatcherAssert.assertThat; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; import java.util.Objects; -import java.util.stream.Stream; +import java.util.regex.Pattern; import org.hamcrest.Matchers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.api.TestMethodOrder; -import cz.vsb.fei.kelvin.unittest.SrcContains; +import cz.vsb.fei.kelvin.unittest.ProjectContains; import cz.vsb.fei.kelvin.unittest.StructureHelper; import cz.vsb.fei.kelvin.unittest.TextFileContains; import cz.vsb.fei.kelvin.unittest.XmlFileContains; +import lab.data.Level; +import lab.data.Score; +import lab.storage.JpaConnector; class ClassStructureTest { StructureHelper helper = StructureHelper.getInstance(ClassStructureTest.class); - - @Test - void lombokAsDependencyTest() throws URISyntaxException { - XmlFileContains xmlFileContains = new XmlFileContains("pom.xml", "/project/dependencies/dependency/artifactId[text() = 'lombok']"); - Path root = TextFileContains.getProjectRoot(getClass()); - assertThat(root, xmlFileContains); - } @Test - void lombokAsAnnotationProcessorTest() throws URISyntaxException { - assertThat(TextFileContains.getProjectRoot(getClass()), new XmlFileContains("pom.xml", "/project/build/plugins/plugin/artifactId[text() = 'maven-compiler-plugin']")); - assertThat(TextFileContains.getProjectRoot(getClass()), new XmlFileContains("pom.xml", "/project/build/plugins/plugin/configuration/annotationProcessorPaths/path/artifactId[text() = 'lombok']")); + void jakartaAndHibernateAsDependencyTest() throws URISyntaxException { + assertThat(TextFileContains.getProjectRoot(getClass()), new XmlFileContains("pom.xml", + "/project/dependencies/dependency/artifactId[text() = 'jakarta.persistence-api']")); + assertThat(TextFileContains.getProjectRoot(getClass()), new XmlFileContains("pom.xml", + "/project/dependencies/dependency/artifactId[text() = 'hibernate-core']")); } @Test - void moduleInfoTest() throws URISyntaxException { - assertThat(TextFileContains.getProjectRoot(getClass()), new TextFileContains("module-info.java", "lombok;")); + void jakartaInModulInfoTest() throws URISyntaxException { + assertThat(TextFileContains.getProjectRoot(getClass()), + new TextFileContains("module-info.java", "jakarta.persistence;")); + assertThat(TextFileContains.getProjectRoot(getClass()), + new TextFileContains("module-info.java", "opens\\slab.data;")); } - @CsvSource({ - "Setup,@Getter,1", - "Setup,@.*Builder,1", - "Setup,@.*Default,3" - }) - @ParameterizedTest(name = "useLombokTest in {1} annotation {2}") - void useLombokConfigTest(String className, String text, int count) throws URISyntaxException, ClassNotFoundException { - Class<?> config = helper.getClass(className); - assertThat(config, new SrcContains(text).count(count)); + @Test + void pesistenceXmlTest() throws URISyntaxException { + ProjectContains projectContains = new ProjectContains("persistence.xml"); + assertThat(TextFileContains.getProjectRoot(getClass()), projectContains); + assertThat(projectContains.getFoundFiles(), Matchers.not(Matchers.hasSize(0))); + Path persistenceXml = projectContains.getFoundFiles().getFirst(); + assertThat(persistenceXml.toAbsolutePath().toString(), + Matchers.endsWith(Paths.get("resources", "META-INF", "persistence.xml").toString())); } - @CsvSource({ - "Score,@Setter,1", - "Score,@Getter,1", - "Score,@AllArgsConstructor,1", - "Score,@EqualsAndHashCode,1", - "Score,@ToString,1" - }) - @ParameterizedTest(name = "useLombokTest in {1} annotation {2}") - void useLombokOrDataTest(String className, String text, int count) throws URISyntaxException, ClassNotFoundException { - Class<?> config = helper.getClass(className); - assertThat(config, Matchers.anyOf(new SrcContains(text).count(count), - new SrcContains("@Data").count(1))); - } - @Test - void recordTest() throws URISyntaxException { - - long recordCount = Stream.concat( - helper.getAllNonInnerClasses().stream(), - helper.getAllInnerClasses().stream()) - .filter(className -> !className.startsWith("javafx")).map(className -> { - try { - return helper.getClassDirectly(className); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - return null; - } - }).filter(Objects::nonNull).filter(clazz -> clazz.isRecord()).count(); - assertThat(recordCount, Matchers.greaterThanOrEqualTo(1L)); - + void useEnumeratedTest() throws URISyntaxException { + assertThat(TextFileContains.getProjectRoot(getClass()), + new TextFileContains("Score.java", "@Enumerated\\(\\s*EnumType.STRING\\s*\\)")); } - + @TestMethodOrder(OrderAnnotation.class) + @Nested + class JpaConnectorTests { + + private Score template = new Score(null, "Tester", 100, Level.EASY); + private JpaConnector connector; + + @BeforeEach + void init() { + connector = new JpaConnector(); + } + + @AfterEach + void cleanUp() { + connector.stop(); + } + + boolean same(Score s1, Score s2) { + return s1.getLevel() == s2.getLevel() && s1.getPoints() == s2.getPoints() + && Objects.equals(s1.getName(), s2.getName()); + } + + @Test + @Order(100) + void jpaScoreInsertTest() { + Score savedScore = connector.save(template); + assertThat(savedScore.getId(), Matchers.notNullValue()); + } + + @Test + @Order(200) + void jpaScoreReadTest() { + List<Score> savedScores = connector.getAll().stream().filter(s -> same(s, template)).toList(); + assertThat(savedScores, Matchers.not(Matchers.hasSize(0))); + } + + @Test + @Order(250) + void jpaReadSortedTest() { + for (int i = 0; i < 20; i++) { + connector.save(template.toBuilder().points(i).build()); + } + List<Score> result = connector.getFirstTen(); + assertThat(result, Matchers.hasSize(10)); + for (int i = 0; i < result.size()-1; i++) { + assertThat(result.get(i).getPoints(), Matchers.greaterThanOrEqualTo(result.get(i+1).getPoints())); + } + } + + @Test + @Order(300) + void jpaScoreModifyTest() { + List<Score> savedScores = connector.getAll().stream().filter(s -> same(s, template)).toList(); + List<Long> savedIds = savedScores.stream().map(Score::getId).toList(); + assertThat(savedScores, Matchers.not(Matchers.hasSize(0))); + for (Score score : savedScores) { + score.setLevel(Level.HARD); + connector.save(score); + } + List<Score> modifiedScores = connector.getAll().stream().filter(s -> savedIds.contains(s.getId())).toList(); + assertThat(modifiedScores, Matchers.not(Matchers.hasSize(0))); + List<Score> originalDataScores = connector.getAll().stream().filter(s -> same(s, template)).toList(); + assertThat(originalDataScores, Matchers.hasSize(0)); + } + + @Test + @Order(400) + void jpaScoreDeleteTest() { + template.setLevel(Level.HARD); + List<Score> savedScores = connector.getAll().stream().filter(s -> same(s, template)).toList(); + List<Long> savedIds = savedScores.stream().map(Score::getId).toList(); + assertThat(savedScores, Matchers.not(Matchers.hasSize(0))); + connector.delete(savedScores); + List<Score> modifiedScores = connector.getAll().stream().filter(s -> savedIds.contains(s.getId())).toList(); + assertThat(modifiedScores, Matchers.hasSize(0)); + List<Score> originalDataScores = connector.getAll().stream().filter(s -> same(s, template)).toList(); + assertThat(originalDataScores, Matchers.hasSize(0)); + } + + @Test + @Order(400) + void jpaMergeTest() { + connector.save(template); + connector.find(template.getId()); + Score copy = template.toBuilder().points(500).build(); + Score result = connector.save(copy); + assertThat(result, Matchers.not(Matchers.sameInstance(copy))); + } + + @Test + @Order(500) + void jpamodifyNoPersistNoMergeTest() throws URISyntaxException, IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException { + template.setName("aaa"); + connector.save(template); + connector.modifyNoPersistOrMerge(template.getId(), score -> score.setName("ok")); + Object em = connector.getEntityManager(); + em.getClass().getMethod("clear").invoke(em); + + assertThat(connector.find(template.getId()).getName(), Matchers.equalTo("ok")); + TextFileContains textFileContains = new TextFileContains("JpaConnector.java", + "void\\s+modifyNoPersistOrMerge[\\s\\S]*}").multiline(true); + assertThat(TextFileContains.getProjectRoot(ClassStructureTest.class), textFileContains); + Path score = textFileContains.getFoundFiles().getFirst(); + String src = Files.readString(score); + String method = Pattern.compile("void\\s+modifyNoPersistOrMerge[\\s\\S]*}").matcher(src).results().findFirst().get().group(); + assertThat(method, Matchers.not(Matchers.containsString("persist"))); + assertThat(method, Matchers.not(Matchers.containsString("merge"))); + } + } }