From e7b8dd9f5669954680494f43a359df58edab2c30 Mon Sep 17 00:00:00 2001 From: jez04 <david.jezek@post.cz> Date: Sat, 15 Mar 2025 02:41:00 +0100 Subject: [PATCH] feat: :tada: solution --- pom.xml | 49 +- src/main/java/lab/Setting.java | 161 +---- src/main/java/lab/data/Score.java | 55 +- src/main/java/lab/game/AngleChange.java | 5 + src/main/java/lab/game/BulletAnimated.java | 8 +- src/main/java/lab/game/ForceChange.java | 5 + src/main/java/lab/game/Ufo.java | 7 +- src/main/java/lab/game/World.java | 15 + src/main/java/lab/gui/App.java | 7 +- src/main/java/lab/gui/GameController.java | 23 + .../lab/storage/ScoreStorageInterface.java | 1 + src/main/java/module-info.java | 1 + src/main/resources/lab/gui/gameWindow.fxml | 3 +- .../jez04/structure/test/AllOfContinue.java | 39 -- .../java/jez04/structure/test/ClassExist.java | 44 -- .../structure/test/ClassStructureTest.java | 65 +- .../structure/test/ContainsInnerClasses.java | 70 --- .../java/jez04/structure/test/HasMethod.java | 95 --- .../jez04/structure/test/HasProperty.java | 91 --- .../jez04/structure/test/IsDescendatOf.java | 24 - .../jez04/structure/test/IsInterface.java | 23 - .../structure/test/ResourceContains.java | 102 ---- .../jez04/structure/test/SrcContains.java | 54 -- .../jez04/structure/test/StructureHelper.java | 573 ------------------ .../structure/test/StructureMatcher.java | 7 - 25 files changed, 193 insertions(+), 1334 deletions(-) create mode 100644 src/main/java/lab/game/AngleChange.java create mode 100644 src/main/java/lab/game/ForceChange.java delete mode 100644 src/test/java/jez04/structure/test/AllOfContinue.java delete mode 100644 src/test/java/jez04/structure/test/ClassExist.java delete mode 100644 src/test/java/jez04/structure/test/ContainsInnerClasses.java delete mode 100644 src/test/java/jez04/structure/test/HasMethod.java delete mode 100644 src/test/java/jez04/structure/test/HasProperty.java delete mode 100644 src/test/java/jez04/structure/test/IsDescendatOf.java delete mode 100644 src/test/java/jez04/structure/test/IsInterface.java delete mode 100644 src/test/java/jez04/structure/test/ResourceContains.java delete mode 100644 src/test/java/jez04/structure/test/SrcContains.java delete mode 100644 src/test/java/jez04/structure/test/StructureHelper.java delete mode 100644 src/test/java/jez04/structure/test/StructureMatcher.java diff --git a/pom.xml b/pom.xml index 3905639..67e399c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,17 +3,42 @@ 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-lab03-v1</artifactId> + <artifactId>java2-lab04-v1</artifactId> <version>0.0.1-SNAPHOST</version> - <name>java2-lab03-v1</name> + <name>java2-lab04-v1</name> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> + <lombok.version>1.18.34</lombok.version> </properties> + <repositories> + <repository> + <id>vsb-education-release</id> + <url>https://artifactory.cs.vsb.cz/repository/education-releases/</url> + </repository> + <repository> + <id>vsb-education-snapshot</id> + <url>https://artifactory.cs.vsb.cz/repository/education-snapshot/</url> + </repository> + </repositories> <dependencies> + <dependency> + <groupId>cz.vsb.fei</groupId> + <artifactId>kelvin-java-unittest-support</artifactId> + <version>[0.1.4,)</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + <scope>provided</scope> + </dependency> + <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> <dependency> @@ -72,18 +97,6 @@ <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.reflections/reflections --> - <dependency> - <groupId>org.reflections</groupId> - <artifactId>reflections</artifactId> - <version>0.10.2</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.hamcrest</groupId> - <artifactId>hamcrest</artifactId> - <version>3.0</version> - <scope>test</scope> - </dependency> </dependencies> <build> <plugins> @@ -92,7 +105,13 @@ <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> - <failOnError>false</failOnError> + <annotationProcessorPaths> + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </path> + </annotationProcessorPaths> </configuration> </plugin> <plugin> diff --git a/src/main/java/lab/Setting.java b/src/main/java/lab/Setting.java index e314258..a392f92 100644 --- a/src/main/java/lab/Setting.java +++ b/src/main/java/lab/Setting.java @@ -2,147 +2,50 @@ package lab; import lab.storage.DbConnector; import lab.storage.ScoreStorageInterface; - +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +@Getter +@Builder(toBuilder = true) +@EqualsAndHashCode +@ToString +@AllArgsConstructor public class Setting { + @Getter private static Setting instance; - private ScoreStorageInterface scoreStorageInterface; - private double gravity; - private double normalBulletSpeed; - private int numberOfUfos; - private double ufoMinPercentageHeight; - private double ufoMinSpeed; - private double ufoMaxSpeed; - private double bulletMinSpeed; - private double bulletMaxSpeed; + + @Default + private ScoreStorageInterface scoreStorageInterface = new DbConnector(); + @Default + private double gravity = 9.81; + @Default + private double normalBulletSpeed = 30; + @Default + private int numberOfUfos = 3; + @Default + private double ufoMinPercentageHeight = 0.3; + @Default + private double ufoMinSpeed = 70; + @Default + private double ufoMaxSpeed = 150; + @Default + private double bulletMinSpeed = 30; + @Default + private double bulletMaxSpeed = 300; public static void configure(Setting setting) { instance = setting; } - private Setting(ScoreStorageInterface scoreStorageInterface, double gravity, double normalBulletSpeed, - int numberOfUfos, double ufoMinPercentageHeight, double ufoMinSpeed, double ufoMaxSpeed, - double bulletMinSpeed, double bulletMaxSpeed) { - super(); - this.scoreStorageInterface = scoreStorageInterface; - this.gravity = gravity; - this.normalBulletSpeed = normalBulletSpeed; - this.numberOfUfos = numberOfUfos; - this.ufoMinPercentageHeight = ufoMinPercentageHeight; - this.ufoMinSpeed = ufoMinSpeed; - this.ufoMaxSpeed = ufoMaxSpeed; - this.bulletMinSpeed = bulletMinSpeed; - this.bulletMaxSpeed = bulletMaxSpeed; - } - - public static Setting getInstance() { - return instance; - } - - public double getGravity() { - return gravity; - } - - public double getNormalBulletSpeed() { - return normalBulletSpeed; - } - - public int getNumberOfUfos() { - return numberOfUfos; - } - - public ScoreStorageInterface getScoreStorageInterface() { - return scoreStorageInterface; - } - - public double getUfoMinPercentageHeight() { - return ufoMinPercentageHeight; - } - - public double getUfoMinSpeed() { - return ufoMinSpeed; - } - - public double getUfoMaxSpeed() { - return ufoMaxSpeed; - } - - public double getBulletMinSpeed() { - return bulletMinSpeed; - } - - public double getBulletMaxSpeed() { - return bulletMaxSpeed; - } - - public static Builder builder() { - return new Builder(); - } - public static Setting getInstanceForHardcoreGame() { return builder().numberOfUfos(50).ufoMinPercentageHeight(0.9).ufoMinSpeed(200).ufoMaxSpeed(500).build(); } - public static class Builder { - private ScoreStorageInterface scoreStorageInterface = new DbConnector(); - private double gravity = 9.81; - private double normalBulletSpeed = 30; - private int numberOfUfos = 3; - private double ufoMinPercentageHeight = 0.3; - private double ufoMinSpeed = 70; - private double ufoMaxSpeed = 150; - private double bulletMinSpeed = 30; - private double bulletMaxSpeed = 300; - - public Builder bulletMaxSpeed(double bulletMaxSpeed) { - this.bulletMaxSpeed = bulletMaxSpeed; - return this; - } - public Builder scoreStorageInterface(ScoreStorageInterface scoreStorageInterface) { - this.scoreStorageInterface = scoreStorageInterface; - return this; - } - - public Builder gravity(double gravity) { - this.gravity = gravity; - return this; - } - - public Builder normalBulletSpeed(double normalBulletSpeed) { - this.normalBulletSpeed = normalBulletSpeed; - return this; - } - - public Builder numberOfUfos(int numberOfUfos) { - this.numberOfUfos = numberOfUfos; - return this; - } - - public Builder ufoMinPercentageHeight(double ufoMinPercentageHeight) { - this.ufoMinPercentageHeight = ufoMinPercentageHeight; - return this; - } - - public Builder ufoMinSpeed(double ufoMinSpeed) { - this.ufoMinSpeed = ufoMinSpeed; - return this; - } - - public Builder ufoMaxSpeed(double ufoMaxSpeed) { - this.ufoMaxSpeed = ufoMaxSpeed; - return this; - } - - public Builder bulletMinSpeed(double bulletMinSpeed) { - this.bulletMinSpeed = bulletMinSpeed; - return this; - } - - public Setting build() { - return new Setting(scoreStorageInterface, gravity, normalBulletSpeed, numberOfUfos, ufoMinPercentageHeight, - ufoMinSpeed, ufoMaxSpeed, bulletMinSpeed, bulletMaxSpeed); - } - } } diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java index 543ebfb..1c64263 100644 --- a/src/main/java/lab/data/Score.java +++ b/src/main/java/lab/data/Score.java @@ -1,8 +1,18 @@ package lab.data; -import java.util.Objects; import java.util.Random; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@AllArgsConstructor +@EqualsAndHashCode +@ToString public class Score { private static final Random RANDOM = new Random(); @@ -10,49 +20,6 @@ public class Score { private String name; private int points; - public Score(String name, int points) { - this.name = name; - this.points = points; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getPoints() { - return points; - } - - public void setPoints(int points) { - this.points = points; - } - - - @Override - public int hashCode() { - return Objects.hash(name, points); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Score other = (Score) obj; - return Objects.equals(name, other.name) && points == other.points; - } - - @Override - public String toString() { - return "Score [name=" + name + ", points=" + points + "]"; - } public static Score generate() { return new Score(getRandomNick(), RANDOM.nextInt(50, 300)); diff --git a/src/main/java/lab/game/AngleChange.java b/src/main/java/lab/game/AngleChange.java new file mode 100644 index 0000000..5bb3467 --- /dev/null +++ b/src/main/java/lab/game/AngleChange.java @@ -0,0 +1,5 @@ +package lab.game; + +public enum AngleChange { + UP, DOWN; +} diff --git a/src/main/java/lab/game/BulletAnimated.java b/src/main/java/lab/game/BulletAnimated.java index 5e3c181..25ba35b 100644 --- a/src/main/java/lab/game/BulletAnimated.java +++ b/src/main/java/lab/game/BulletAnimated.java @@ -14,8 +14,8 @@ public class BulletAnimated extends Bullet { private final Point2D initVelocity; private Cannon cannon; private static Image image = new Image(BulletAnimated.class.getResourceAsStream("fireball-transparent.gif")); - private List<HitListener> hitListeners = - new ArrayList<>(); + + private List<HitListener> hitListeners = new ArrayList<>(); public BulletAnimated(World world, Cannon cannon, Point2D position, Point2D velocity, Point2D acceleration) { super(world, position, velocity, acceleration); @@ -49,11 +49,11 @@ public class BulletAnimated extends Bullet { public boolean removeHitListener(HitListener o) { return hitListeners.remove(o); } - + private void fireUfoDestroyed() { for (HitListener hitListener : hitListeners) { hitListener.ufoDestroyed(); } } - + } \ No newline at end of file diff --git a/src/main/java/lab/game/ForceChange.java b/src/main/java/lab/game/ForceChange.java new file mode 100644 index 0000000..b8cadc9 --- /dev/null +++ b/src/main/java/lab/game/ForceChange.java @@ -0,0 +1,5 @@ +package lab.game; + +public enum ForceChange { + UP, DOWN; +} diff --git a/src/main/java/lab/game/Ufo.java b/src/main/java/lab/game/Ufo.java index 0d93233..9aa6bdf 100644 --- a/src/main/java/lab/game/Ufo.java +++ b/src/main/java/lab/game/Ufo.java @@ -1,5 +1,6 @@ package lab.game; +import java.time.LocalDateTime; import java.util.Random; import org.apache.logging.log4j.LogManager; @@ -18,7 +19,7 @@ public class Ufo extends WorldEntity implements Collisionable { private static final Random RANDOM = new Random(); private Image image; private Point2D velocity; - + public Ufo(World world) { this(world, new Point2D(RANDOM.nextDouble(world.getWidth()), @@ -74,7 +75,11 @@ public class Ufo extends WorldEntity implements Collisionable { public void hitBy(Collisionable another) { log.trace("Ufo hitted by {}.", another); if (another instanceof BulletAnimated || another instanceof Bullet) { + world.add(new UfoDestroyLog(LocalDateTime.now(), getPosition())); world.remove(this); } } + + record UfoDestroyLog(LocalDateTime time, Point2D position) {} + } diff --git a/src/main/java/lab/game/World.java b/src/main/java/lab/game/World.java index 6404f19..929445f 100644 --- a/src/main/java/lab/game/World.java +++ b/src/main/java/lab/game/World.java @@ -8,7 +8,10 @@ import java.util.List; import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import lab.Setting; +import lab.game.Ufo.UfoDestroyLog; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class World { public static final Point2D GRAVITY = new Point2D(0, Setting.getInstance().getGravity()); @@ -19,6 +22,7 @@ public class World { private List<DrawableSimulable> entities; private Collection<DrawableSimulable> entitiesToRemove = new LinkedList<>(); private Collection<DrawableSimulable> entitiesToAdd = new LinkedList<>(); + private List<UfoDestroyLog> destroyLogs = new LinkedList<>(); private Cannon cannon; // private BulletAnimated bulletAnimated; @@ -37,6 +41,17 @@ public class World { } } + + public void add(UfoDestroyLog ufoDestroyLog) { + destroyLogs.add(ufoDestroyLog); + } + + public void pringDestroylog() { + for (UfoDestroyLog ufoDestroyLog : destroyLogs) { + log.info(ufoDestroyLog); + } + } + public void draw(GraphicsContext gc) { gc.clearRect(0, 0, width, height); diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index 8f3f163..4ea74e5 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -24,7 +24,7 @@ public class App extends Application { public static void main(String[] args) { log.info("Application lauched"); - Setting.configure(Setting.getInstanceForHardcoreGame()); + Setting.configure(Setting.getInstanceForHardcoreGame().toBuilder().ufoMinPercentageHeight(0.4).build()); launch(args); } @@ -34,7 +34,7 @@ public class App extends Application { // Construct a main window with a canvas. FXMLLoader gameLoader = new FXMLLoader(getClass().getResource("/lab/gui/gameWindow.fxml")); Parent root = gameLoader.load(); - GameController gameController = gameLoader.getController(); + gameController = gameLoader.getController(); Scene scene = new Scene(root); primaryStage.setScene(scene); primaryStage.setTitle("Java 2 - 2nd laboratory"); @@ -54,6 +54,9 @@ public class App extends Application { } private void exitProgram(WindowEvent evt) { + if (gameController != null) { + gameController.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 7d15ecb..0fc2551 100644 --- a/src/main/java/lab/gui/GameController.java +++ b/src/main/java/lab/gui/GameController.java @@ -15,6 +15,8 @@ import javafx.scene.control.Slider; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseEvent; import lab.Setting; import lab.data.Score; import lab.game.BulletAnimated; @@ -34,6 +36,9 @@ public class GameController { @FXML private Button btnLoadFirstTen; + @FXML + private Button btnDelete; + @FXML private Slider angle; @@ -88,6 +93,22 @@ public class GameController { updateScoreTable(Setting.getInstance().getScoreStorageInterface().getFirstTen()); } + @FXML + void keyPressed(KeyEvent event) { + log.info(event.getCode()); + event.consume(); + } + + @FXML + void canvasClicked(MouseEvent event) { + canvas.requestFocus(); + } + + @FXML + void keyReleased(KeyEvent event) { + + } + private void updateScoreTable(List<Score> scores) { this.scores.getItems().clear(); this.scores.getItems().addAll(scores); @@ -119,6 +140,7 @@ public class GameController { initStorage(); log.info("Screeen initialized."); + canvas.requestFocus(); } private void initStorage() { @@ -127,6 +149,7 @@ public class GameController { } public void stop() { + timer.getWorld().pringDestroylog(); timer.stop(); } diff --git a/src/main/java/lab/storage/ScoreStorageInterface.java b/src/main/java/lab/storage/ScoreStorageInterface.java index 67ee80d..c7664c2 100644 --- a/src/main/java/lab/storage/ScoreStorageInterface.java +++ b/src/main/java/lab/storage/ScoreStorageInterface.java @@ -1,5 +1,6 @@ package lab.storage; +import java.util.Collection; import java.util.List; import lab.data.Score; diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 75517d2..3f19883 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -4,6 +4,7 @@ module cz.vsb.fei.java2.lab03_module { requires javafx.base; requires java.sql; requires org.apache.logging.log4j; + requires static lombok; opens lab.gui to javafx.fxml; opens lab.data to javafx.base; diff --git a/src/main/resources/lab/gui/gameWindow.fxml b/src/main/resources/lab/gui/gameWindow.fxml index 2579b5b..e0d12e5 100644 --- a/src/main/resources/lab/gui/gameWindow.fxml +++ b/src/main/resources/lab/gui/gameWindow.fxml @@ -48,7 +48,7 @@ <Insets /> </BorderPane.margin> <children> - <Canvas fx:id="canvas" height="306.0" style="-fx-border-width: 3px; -fx-border-style: SOLID; -fx-border-color: RGB(100.0,0.0,0.0);" width="582.0" StackPane.alignment="TOP_LEFT" /> + <Canvas fx:id="canvas" focusTraversable="true" height="306.0" onKeyPressed="#keyPressed" onKeyReleased="#keyReleased" onMouseClicked="#canvasClicked" style="-fx-border-width: 3px; -fx-border-style: SOLID; -fx-border-color: RGB(100.0,0.0,0.0);" width="582.0" StackPane.alignment="TOP_LEFT" /> </children> </StackPane> </left> @@ -67,6 +67,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" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Delete score" /> </children> </VBox> </center> diff --git a/src/test/java/jez04/structure/test/AllOfContinue.java b/src/test/java/jez04/structure/test/AllOfContinue.java deleted file mode 100644 index 8eb250b..0000000 --- a/src/test/java/jez04/structure/test/AllOfContinue.java +++ /dev/null @@ -1,39 +0,0 @@ -package jez04.structure.test; - -import java.util.Arrays; -import java.util.List; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.hamcrest.Matcher; - -public class AllOfContinue<T> extends BaseMatcher<T> { - - private final List<Matcher<? super T>> matchers; - - @SafeVarargs - public AllOfContinue(Matcher<? super T> ... matchers) { - this(Arrays.asList(matchers)); - } - - public AllOfContinue(List<Matcher<? super T>> matchers) { - this.matchers = matchers; - } - - @Override - public boolean matches(Object o) { - for (Matcher<? super T> matcher : matchers) { - if (!matcher.matches(o)) { -// matcher.describeMismatch(o, mismatch); - return false; - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendList("(", " " + "and" + " ", ")", matchers); - } - -} diff --git a/src/test/java/jez04/structure/test/ClassExist.java b/src/test/java/jez04/structure/test/ClassExist.java deleted file mode 100644 index 7e1f9b7..0000000 --- a/src/test/java/jez04/structure/test/ClassExist.java +++ /dev/null @@ -1,44 +0,0 @@ -package jez04.structure.test; - -import org.hamcrest.Description; - -public class ClassExist extends StructureMatcher<String> { - - private String className; - private boolean useRegExp; - private boolean caseSensitive; - - public ClassExist(String className) { - this(className, true, false); - } - - public ClassExist(String className, boolean caseSensitive, boolean useRegExp) { - this.className = className; - this.useRegExp = useRegExp; - this.caseSensitive = caseSensitive; - } - - @Override - public boolean matches(Object actual) { - if (useRegExp) { - return structureHelper.getAllClasses().stream().anyMatch( - c -> caseSensitive ? c.matches(className) : c.toLowerCase().matches(className.toLowerCase())); - } else { - return structureHelper.getAllClasses().stream().anyMatch( - c -> caseSensitive ? c.endsWith(className) : c.toLowerCase().endsWith(className.toLowerCase())); - } - - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("class/interface with name '%s' comparsion params(%s %s) exists", className, - caseSensitive ? "" : "no case sensitive", useRegExp ? "using regexp" : "")); - } - - @Override - public void describeMismatch(Object item, Description description) { - description.appendValueList("no class match from:\n ", "\n ", "", structureHelper.getAllClasses()); - } - -} diff --git a/src/test/java/jez04/structure/test/ClassStructureTest.java b/src/test/java/jez04/structure/test/ClassStructureTest.java index 7eb5fb7..43e2f1c 100644 --- a/src/test/java/jez04/structure/test/ClassStructureTest.java +++ b/src/test/java/jez04/structure/test/ClassStructureTest.java @@ -1,27 +1,60 @@ package jez04.structure.test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.endsWith; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.startsWith; -import static org.hamcrest.Matchers.stringContainsInOrder; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; + import java.net.URISyntaxException; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.List; +import java.nio.file.Path; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import cz.vsb.fei.kelvin.unittest.StructureHelper; +import cz.vsb.fei.kelvin.unittest.TextFileContains; +import cz.vsb.fei.kelvin.unittest.XmlFileContains; class ClassStructureTest { - StructureHelper helper = StructureHelper.getInstance(); + 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']")); + } + + @Test + void moduleInfoTest() throws URISyntaxException { + assertThat(TextFileContains.getProjectRoot(getClass()), new TextFileContains("module-info.java", "lombok;")); + } + + @CsvSource({ + "@Getter,1", + "@Setter,1", + "@Log.*,1", + "@.*ArgsConstructor,1", + "@ToString,1", + "@Getter,3", + "@Setter,3", + "@Log.*,3", + "@.*ArgsConstructor,2", + "@ToString,3", + "@Log.*,5", + "@ToString,5" }) + @ParameterizedTest(name = "use Lombok Annotation {0} {1} times") + void useLombokConfigTest(String text, int count) throws URISyntaxException, ClassNotFoundException { + assertThat(TextFileContains.getProjectRoot(getClass()), + new TextFileContains(".*\\.java", text).count(count).useRegExpForName(true)); + } } diff --git a/src/test/java/jez04/structure/test/ContainsInnerClasses.java b/src/test/java/jez04/structure/test/ContainsInnerClasses.java deleted file mode 100644 index 5c79529..0000000 --- a/src/test/java/jez04/structure/test/ContainsInnerClasses.java +++ /dev/null @@ -1,70 +0,0 @@ -package jez04.structure.test; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.List; -import java.util.stream.Collectors; - -import org.hamcrest.Description; - -public class ContainsInnerClasses extends StructureMatcher<Class<?>> { - - private String methodNameRegexp; - private boolean caseSensitive = true; - private boolean useRegExp = false; - private int count = 1; - private List<Class<?>> params; - - public ContainsInnerClasses(String methodNameRegexp) { - this.methodNameRegexp = methodNameRegexp; - } - - public ContainsInnerClasses caseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; - return this; - } - - public ContainsInnerClasses count(int count) { - this.count = count; - return this; - } - - public ContainsInnerClasses useRegExp(boolean useRegExp) { - this.useRegExp = useRegExp; - return this; - } - - @Override - public boolean matches(Object actual) { - if (actual instanceof Class c) { - long lamdaCount = structureHelper.countMethodRegexp(c, "lambda\\$.*"); - long innerClassCount = structureHelper.countClassesRegexp(c.getCanonicalName()+"\\$.*"); - long methodRefCount = 0; - try { - methodRefCount = structureHelper.countMethodReference(c); - } catch (URISyntaxException | IOException e) { - System.out.println("Cannot count method references"); - e.printStackTrace(); - } - return lamdaCount + innerClassCount+methodRefCount >= count; - } - return false; - } - - @Override - public void describeTo(Description description) { - params.stream().map(Class::getName).collect(Collectors.joining(", ")); - description.appendText( - String.format("Class should have inner classses or lambdas name (regexp) of type %s %s %s with params types %s", - methodNameRegexp, caseSensitive ? "" : "ignore case", "")); - } - - @Override - public void describeMismatch(Object item, Description description) { - if (item instanceof Class c) { - description.appendValueList("no method match from:\n ", "\n ", "", c.getDeclaredMethods()); - } else { - description.appendText("mismatched item is not class type"); - } - } -} diff --git a/src/test/java/jez04/structure/test/HasMethod.java b/src/test/java/jez04/structure/test/HasMethod.java deleted file mode 100644 index 142fec8..0000000 --- a/src/test/java/jez04/structure/test/HasMethod.java +++ /dev/null @@ -1,95 +0,0 @@ -package jez04.structure.test; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.hamcrest.Description; - -public class HasMethod extends StructureMatcher<Class<?>> { - - private String methodNameRegexp; - private Class<?> returnType; - private boolean caseSensitive = true; - private boolean useRegExp = false; - private Boolean abstractTag = null; - private Boolean finalTag = null; - private int count = 1; - private List<Class<?>> params; - - public HasMethod(String methodNameRegexp, Class<?> returnType, Class<?>... params) { - this.methodNameRegexp = methodNameRegexp; - this.returnType = returnType; - this.params = List.of(params); - } - - public HasMethod caseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; - return this; - } - - public HasMethod abstractTag(Boolean abstractTag) { - this.abstractTag = abstractTag; - return this; - } - - public HasMethod finalTag(Boolean finalTag) { - this.finalTag = finalTag; - return this; - } - - public HasMethod count(int count) { - this.count = count; - return this; - } - - public HasMethod useRegExp(boolean useRegExp) { - this.useRegExp = useRegExp; - return this; - } - - @Override - public boolean matches(Object actual) { - if (actual instanceof Class c) { - List<Method> methods = Arrays.asList(c.getDeclaredMethods()); - Stream<Method> streamOfMethods; - if (useRegExp) { - streamOfMethods = methods.stream().filter(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())); - - } else { - streamOfMethods = methods.stream().filter(m -> caseSensitive ? m.getName().endsWith(methodNameRegexp) - : m.getName().toLowerCase().endsWith(methodNameRegexp.toLowerCase())); - } - streamOfMethods = streamOfMethods - .filter(m -> returnType != null ? returnType.equals(m.getReturnType()) : true) - .filter(m -> finalTag != null ? Modifier.isAbstract(m.getModifiers()) == abstractTag.booleanValue() - : true) - .filter(m -> abstractTag != null ? Modifier.isFinal(m.getModifiers()) == finalTag.booleanValue() - : true); - long co = streamOfMethods.count(); - return co >= count; - } - return false; - } - - @Override - public void describeTo(Description description) { - params.stream().map(Class::getName).collect(Collectors.joining(", ")); - description.appendText( - String.format("Class should have method name (regexp) of type %s %s %s with params types %s", - returnType, methodNameRegexp, caseSensitive ? "" : "ignore case", "")); - } - - @Override - public void describeMismatch(Object item, Description description) { - if (item instanceof Class c) { - description.appendValueList("no method match from:\n ", "\n ", "", c.getDeclaredMethods()); - } else { - description.appendText("mismatched item is not class type"); - } - } -} diff --git a/src/test/java/jez04/structure/test/HasProperty.java b/src/test/java/jez04/structure/test/HasProperty.java deleted file mode 100644 index 0e7098d..0000000 --- a/src/test/java/jez04/structure/test/HasProperty.java +++ /dev/null @@ -1,91 +0,0 @@ -package jez04.structure.test; - -import java.lang.reflect.Field; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import org.hamcrest.Description; - -public class HasProperty extends StructureMatcher<Class<?>> { - - private String propertyNameRegexp; - private Class<?> type; - private Predicate<Type> genericTypeFilter; - private Predicate<Class<?>> typeFilter; - private Boolean array = false; - private boolean caseSensitive; - private Class<?> annotation = null; - private int count = 1; - - public HasProperty(String propertyNameRegexp, Class<?> type, Boolean array) { - this(propertyNameRegexp, type, array, true); - } - - public HasProperty(String propertyNameRegexp, Class<?> type, Boolean array, boolean caseSensitive) { - this.propertyNameRegexp = propertyNameRegexp; - this.type = type; - this.array = array; - this.caseSensitive = caseSensitive; - } - - public HasProperty annotation(Class<?> annotation) { - this.annotation = annotation; - return this; - } - - public HasProperty typeFilter(Predicate<Class<?>> typeFilter) { - this.typeFilter = typeFilter; - return this; - } - - public HasProperty genericTypeFilter(Predicate<Type> genericTypeFilter) { - this.genericTypeFilter = genericTypeFilter; - return this; - } - - public HasProperty count(int count) { - this.count = count; - return this; - } - - @Override - public boolean matches(Object actual) { - if (actual instanceof Class c) { - Stream<?> streamOfResults; - List<Field> fields = Arrays.asList(c.getDeclaredFields()); - Stream<Field> streamOfFields = fields.stream() - .filter(f -> caseSensitive ? f.getName().matches(propertyNameRegexp) - : f.getName().toLowerCase().matches(propertyNameRegexp.toLowerCase())) - .filter(f -> type != null ? f.getType().equals(type) : true) - .filter(f -> array != null ? f.getType().isAnnotation() == array.booleanValue() : true) - .filter(f -> genericTypeFilter != null ? genericTypeFilter.test(f.getGenericType()) : true) - .filter(f -> typeFilter != null ? typeFilter.test(f.getType()) : true); - streamOfResults = streamOfFields; - if (annotation != null) { - streamOfResults = streamOfFields.flatMap(f -> Arrays.asList(f.getAnnotations()).stream()) - .map(a -> a.annotationType()).filter(a -> a.equals(annotation)); - } - long actualCount = streamOfResults.count(); - return this.count <= actualCount; - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("Class should have field of type %s%s with name match regexp '%s'%s", type, - array != null && array ? "[]" : "", propertyNameRegexp, caseSensitive ? "" : "ignore case")); - } - - @Override - public void describeMismatch(Object item, Description description) { - if (item instanceof Class c) { - description.appendValueList("none of", ", ", "match", c.getDeclaredFields()); - } else { - description.appendText("mismatched item is not class type"); - } - } -} diff --git a/src/test/java/jez04/structure/test/IsDescendatOf.java b/src/test/java/jez04/structure/test/IsDescendatOf.java deleted file mode 100644 index a202faa..0000000 --- a/src/test/java/jez04/structure/test/IsDescendatOf.java +++ /dev/null @@ -1,24 +0,0 @@ -package jez04.structure.test; - -import org.hamcrest.Description; - -public class IsDescendatOf extends StructureMatcher<Class<?>> { - - private String className; - public IsDescendatOf(String className) { - this.className = className; - } - @Override - public boolean matches(Object actual) { - if(actual instanceof Class c) { - return structureHelper.getClass(className).isAssignableFrom(c); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("cass shoud be descendant of %s", className)); - } - -} diff --git a/src/test/java/jez04/structure/test/IsInterface.java b/src/test/java/jez04/structure/test/IsInterface.java deleted file mode 100644 index 2abdee2..0000000 --- a/src/test/java/jez04/structure/test/IsInterface.java +++ /dev/null @@ -1,23 +0,0 @@ -package jez04.structure.test; - -import org.hamcrest.Description; - -public class IsInterface extends StructureMatcher<Class<?>> { - - public IsInterface() { - } - - @Override - public boolean matches(Object actual) { - if (actual instanceof Class c) { - return c.isInterface(); - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("value should be interface")); - } - -} diff --git a/src/test/java/jez04/structure/test/ResourceContains.java b/src/test/java/jez04/structure/test/ResourceContains.java deleted file mode 100644 index e7d9277..0000000 --- a/src/test/java/jez04/structure/test/ResourceContains.java +++ /dev/null @@ -1,102 +0,0 @@ -package jez04.structure.test; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Pattern; - -import org.hamcrest.Description; - -public class ResourceContains extends StructureMatcher<String> { - private String regexp; - private boolean caseInsensitive; - private boolean srcFound; - private int count = 1; - - public ResourceContains(String regexp, boolean caseInsensitive) { - this.regexp = regexp; - this.caseInsensitive = caseInsensitive; - } - - public ResourceContains count(int count) { - this.count = count; - return this; - } - - @Override - public boolean matches(Object actual) { - srcFound = true; - List<Path> foundResources = new LinkedList<>(); - Pattern p; - if (caseInsensitive) { - p = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE); - } else { - p = Pattern.compile(regexp); - } - try { - URL myClassUrl = StructureHelper.class.getResource(this.getClass().getSimpleName() + ".class"); - Path classRoot = Paths.get(myClassUrl.toURI()); - while (!"test-classes".equals(classRoot.getFileName().toString()) - && !"classes".equals(classRoot.getFileName().toString())) { - classRoot = classRoot.getParent(); - } - Path resourcesRoot = classRoot.getParent().getParent().resolve(Paths.get("src", "main", "resources")); - System.out.println("resources root: " + resourcesRoot); - Files.walkFileTree(resourcesRoot, new FileVisitor<Path>() { - - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (p.matcher(file.getFileName().toString()).matches()) { - foundResources.add(file); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - }); - return foundResources.size() >= count; - } catch (URISyntaxException | IOException e) { - srcFound = false; - e.printStackTrace(); - return false; - } - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("Source code of class shoud contains regexp '%s'%s", regexp, - caseInsensitive ? " in case insensitive mode" : "")); - } - - @Override - public void describeMismatch(Object item, Description description) { - if (srcFound) { - description - .appendText(String.format("source code of class %s do not contains substring that match reg exp")); - } else { - description.appendText(String.format("source code of class %s was not found")); - } - } - -} diff --git a/src/test/java/jez04/structure/test/SrcContains.java b/src/test/java/jez04/structure/test/SrcContains.java deleted file mode 100644 index 4ed7d6c..0000000 --- a/src/test/java/jez04/structure/test/SrcContains.java +++ /dev/null @@ -1,54 +0,0 @@ -package jez04.structure.test; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.regex.Pattern; - -import org.hamcrest.Description; - -public class SrcContains extends StructureMatcher<Class<?>> { - private String regexp; - private boolean caseInsensitive; - private boolean srcFound; - - public SrcContains(String regexp, boolean caseInsensitive) { - this.regexp = regexp; - this.caseInsensitive = caseInsensitive; - } - - @Override - public boolean matches(Object actual) { - srcFound = true; - if (actual instanceof Class c) { - Pattern p = Pattern.compile(regexp); - if (caseInsensitive) { - p = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE); - } - try { - return p.matcher(structureHelper.getSourceCode(c)).find(); - } catch (URISyntaxException | IOException e) { - srcFound = false; - e.printStackTrace(); - return false; - } - } - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("Source code of class shoud contains regexp '%s'%s", regexp, - caseInsensitive ? " in case insensitive mode" : "")); - } - - @Override - public void describeMismatch(Object item, Description description) { - if (srcFound) { - description - .appendText(String.format("source code of class %s do not contains substring that match reg exp", item)); - } else { - description.appendText(String.format("source code of class %s was not found")); - } - } - -} diff --git a/src/test/java/jez04/structure/test/StructureHelper.java b/src/test/java/jez04/structure/test/StructureHelper.java deleted file mode 100644 index 6ccabb4..0000000 --- a/src/test/java/jez04/structure/test/StructureHelper.java +++ /dev/null @@ -1,573 +0,0 @@ -package jez04.structure.test; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.junit.jupiter.api.Assertions; -import org.reflections.Configuration; -import org.reflections.Reflections; -import org.reflections.scanners.Scanners; -import org.reflections.util.ConfigurationBuilder; - -class StructureHelper { - - private static StructureHelper singeltonInstance; - - public static StructureHelper getInstance() { - if (singeltonInstance == null) { - singeltonInstance = new StructureHelper(); - } - return singeltonInstance; - } - - Set<String> allClasses = getNameOfAllClasses(); - - private StructureHelper() { - /* hide public one */ - } - - public Set<String> getAllClasses() { - return allClasses; - } - - public void isInterface(Class<?> c) { - assertTrue(c.isInterface(), c.getName() + " have to be interface."); - } - - public void classExist(String name) { - classExist(name, true); - } - - public void classExist(String name, boolean caseSensitive) { - assertTrue( - allClasses.stream() - .anyMatch(c -> caseSensitive ? c.endsWith(name) : c.toLowerCase().endsWith(name.toLowerCase())), - "Class/Interface " + name + " not found"); - } - - public void classExistRegexp(String name) { - classExistRegexp(name, true); - } - - public void classExistRegexp(String name, boolean caseSensitive) { - assertTrue( - allClasses.stream() - .anyMatch(c -> caseSensitive ? c.matches(name) : c.toLowerCase().matches(name.toLowerCase())), - "Class/Interface " + name + " not found"); - } - - public Class<?> getClassDirectly(String name) { - return loadClass(name, name); - } - - public Class<?> getClassRegexp(String name) { - return getClassRegexp(name, true); - } - - public Class<?> getClassRegexp(String name, boolean caseSensitive) { - String className = allClasses.stream() - .filter(c -> caseSensitive ? c.matches(name) : c.toLowerCase().matches(name.toLowerCase())).findAny() - .orElse(null); - if (className == null) { - Assertions.fail("Class " + name + " not found."); - } - return loadClass(name, className); - } - - public Class<?> getClass(String name) { - return getClass(name, true); - } - - public Class<?> getClass(String name, boolean caseSensitive) { - String className = allClasses.stream() - .filter(c -> caseSensitive ? c.endsWith(name) : c.toLowerCase().endsWith(name.toLowerCase())).findAny() - .orElse(null); - if (className == null) { - Assertions.fail("Class " + name + " not found."); - } - return loadClass(name, className); - } - - private Class<?> loadClass(String name, String className) { - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (PrintStream ps = new PrintStream(baos, true)) { - e.printStackTrace(ps); - } catch (Exception e2) { - Assertions.fail(e2.getMessage()); - } - String stackTrace = baos.toString(); - Assertions.fail("Class " + name + " not found.\n" + stackTrace); - return null; - } - } - - public org.hamcrest.Matcher<Class<?>> hasProperty(String propertyNameRegexp, Class<?> type, boolean array) { - return new HasProperty(propertyNameRegexp, type, array); - } - - public void hasProperty(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array) { - hasProperty(classDef, propertyNameRegexp, type, array, true); - } - - public void hasProperty(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array, - boolean caseSensitive) { - assertTrue(hasPropertyB(classDef, propertyNameRegexp, type, array, caseSensitive), - "No field " + propertyNameRegexp + " of type " + type.getName() + " (is array " + array + ") in class " - + classDef.getName()); - } - - public boolean hasPropertyB(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array, - boolean caseSensitive) { - List<Field> fields = Arrays.asList(classDef.getDeclaredFields()); - return fields.stream().anyMatch(f -> { - if (caseSensitive ? f.getName().matches(propertyNameRegexp) - : f.getName().toLowerCase().matches(propertyNameRegexp.toLowerCase())) { - if (array) { - return f.getType().isArray() && f.getType().getComponentType().equals(type); - } else { - return f.getType().equals(type); - } - } - return false; - }); - } - - public void hasPropertyWithAnnotation(Class<?> classDef, String propertyNameRegexp, Class<?> annotation) { - hasPropertyWithAnnotation(classDef, propertyNameRegexp, annotation, true); - } - - public void hasPropertyWithAnnotation(Class<?> classDef, String propertyNameRegexp, Class<?> annotation, - boolean caseSensitive) { - List<Field> fields = Arrays.asList(classDef.getDeclaredFields()); - assertTrue( - fields.stream() - .filter(f -> caseSensitive ? f.getName().matches(propertyNameRegexp) - : f.getName().toLowerCase().matches(propertyNameRegexp.toLowerCase())) - .flatMap(f -> Arrays.asList(f.getAnnotations()).stream()).map(a -> a.annotationType()) - .anyMatch(a -> a.equals(annotation)), - "No field " + propertyNameRegexp + " with annotation " + annotation.getName() + " in class " - + classDef.getName()); - } - - public void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType) { - hasMethod(interfaceDef, methodName, returnType, true); - } - - public void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, boolean caseSensitive) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName); - assertTrue( - methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())) - .anyMatch(m -> m.getReturnType().equals(returnType)), - "Method " + methodName + " not return " + returnType.getName()); - } - - public void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, Class<?>... params) { - hasMethod(interfaceDef, methodName, true, returnType, params); - } - - public void hasMethod(Class<?> interfaceDef, String methodName, boolean caseSensitive, Class<?> returnType, - Class<?>... params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - assertTrue( - methods.stream() - .anyMatch(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())), - "No method " + methodName); - assertTrue( - methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType)) - .anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))), - "Method " + methodName + " has no all parrams:" - + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); - } - - public Method getMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, Class<?>... params) { - return getMethod(interfaceDef, methodName, true, returnType, params); - } - - public Method getMethod(Class<?> interfaceDef, String methodName, boolean caseSensitive, Class<?> returnType, - Class<?>... params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - List<Method> foundMethods = methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType)) - .filter(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))).toList(); - if (foundMethods.isEmpty()) { - fail("No method " + methodName + " found"); - } - if (foundMethods.size() > 1) { - fail("More then one method " + methodName + " found"); - } - return foundMethods.get(0); - } - - public long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp) { - return countMethodRegexp(interfaceDef, methodNameRegexp, true); - } - - public long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, boolean caseSensitive) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - return methods.stream().filter(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())).count(); - } - - public long countMethodReference(Class<?> interfaceDef) throws URISyntaxException, IOException { - Pattern p = Pattern.compile("::"); - Matcher m = p.matcher(getSourceCode(interfaceDef)); - return m.results().count(); - } - - public long countMethodReferenceOn(Class<?> interfaceDef, String to) { - try { - Pattern p = Pattern.compile(to + "::"); - Matcher m = p.matcher(getSourceCode(interfaceDef)); - return m.results().count(); - } catch (URISyntaxException | IOException e) { - e.printStackTrace(); - return 0; - } - } - - public long countClassesRegexp(String classNameRegexp) { - return countClassesRegexp(classNameRegexp, true); - } - - public long countClassesRegexp(String classNameRegexp, boolean caseSensitive) { - return getNameOfAllClasses().stream().filter(className -> caseSensitive ? className.matches(classNameRegexp) - : className.toLowerCase().matches(classNameRegexp.toLowerCase())).count(); - } - - public void hasConstructor(Class<?> classDef, Class<?>... params) { - getConstructor(classDef, params); - } - - public Constructor<?> getConstructor(Class<?> classDef, Class<?>... params) { - List<Constructor<?>> constructors = Arrays.asList(classDef.getConstructors()); - List<Constructor<?>> foundConstructors = constructors.stream() - .filter(m -> m.getParameterCount() == params.length) - .filter(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))).toList(); - if (foundConstructors.isEmpty()) { - fail("No constructor found with parameters: " - + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); - } - if (foundConstructors.size() > 1) { - fail("More then one constructor found with parameters: " - + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); - } - return foundConstructors.get(0); - } - - public void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType, - Class<?>... params) { - hasMethodRegexp(interfaceDef, methodNameRegexp, true, returnType, params); - } - - public void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, boolean caseSensitive, - Class<?> returnType, Class<?>... params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - assertTrue( - methods.stream() - .anyMatch(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())), - "No method " + methodNameRegexp); - assertTrue( - methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType)) - .anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))), - "Method " + methodNameRegexp + " has no all parrams:" - + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); - } - - public boolean hasMethodRegexpTest(Class<?> interfaceDef, String methodNameRegexp, boolean caseSensitive, - Class<?> returnType, Class<?>... params) { - return hasMethodRegexpTest(interfaceDef, methodNameRegexp, caseSensitive, returnType, List.of(params)); - } - - public boolean hasMethodRegexpTest(Class<?> interfaceDef, String methodNameRegexp, boolean caseSensitive, - Class<?> returnType, List<Class<?>> params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - if (!methods.stream().anyMatch(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase()))) { - return false; - } - return methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType)) - .anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(params)); - } - - public long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType, - Class<?>... params) { - return countMethodRegexp(interfaceDef, methodNameRegexp, true, returnType, params); - } - - public long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, boolean caseSensitive, - Class<?> returnType, Class<?>... params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - assertTrue( - methods.stream() - .anyMatch(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())), - "No method " + methodNameRegexp); - return methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodNameRegexp) - : m.getName().toLowerCase().matches(methodNameRegexp.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType)) - .filter(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))).count(); - } - - public boolean hasMethodTest(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName, - boolean caseSensitive, Class<?> returnType, Class<?>... params) { - return hasMethodTest(interfaceDef, finalTag, abstractTag, methodName, caseSensitive, returnType, List.of(params)); - } - public boolean hasMethodTest(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName, - boolean caseSensitive, Class<?> returnType, List<Class<?>> params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - if (!methods.stream().anyMatch(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase()))) { - return false; - } - return methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType) - && (Modifier.isAbstract(m.getModifiers()) == abstractTag) - && (Modifier.isFinal(m.getModifiers()) == finalTag)) - .anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(params)); - } - - public void hasMethod(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName, - Class<?> returnType, Class<?>... params) { - hasMethod(interfaceDef, finalTag, abstractTag, methodName, true, returnType, params); - } - - public void hasMethod(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName, - boolean caseSensitive, Class<?> returnType, Class<?>... params) { - List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); - assertTrue( - methods.stream() - .anyMatch(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())), - "No method " + methodName); - assertTrue( - methods.stream() - .filter(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())) - .filter(m -> m.getReturnType().equals(returnType) - && (Modifier.isAbstract(m.getModifiers()) == abstractTag) - && (Modifier.isFinal(m.getModifiers()) == finalTag)) - .anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))), - "Method " + methodName + " has no all params:" - + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); - } - - public boolean isDescendatOf(Class<?> clazz, String interfaceName) { - return getClass(interfaceName).isAssignableFrom(clazz); - } - - public void hasImplements(Class<?> clazz, String... interfaceNames) { - List<Class<?>> interfaces = new ArrayList<>(); - Arrays.asList(interfaceNames).stream().map(name -> getClass(name)).forEach(c -> interfaces.add(c)); - assertTrue(Arrays.asList(clazz.getInterfaces()).containsAll(interfaces), "Class not implements all interfaces:" - + interfaces.stream().map(Class::getName).collect(Collectors.joining(", "))); - } - - public void hasExtends(Class<?> clazz, String parentName) { - Class<?> parent = getClass(parentName); - assertTrue(clazz.getSuperclass().equals(parent), - "Class " + clazz.getName() + " not extends class " + parentName); - } - - public void hasExtends(Class<?> clazz, Class<?> parent) { - assertTrue(clazz.getSuperclass().equals(parent), - "Class " + clazz.getName() + " not extends class " + parent.getCanonicalName()); - } - - public void hasMethod(Class<?> interfaceDef, String methodName) { - hasMethod(interfaceDef, methodName, true); - } - - public void hasMethod(Class<?> interfaceDef, String methodName, boolean caseSensitive) { - List<Method> methods = Arrays.asList(interfaceDef.getMethods()); - assertTrue( - methods.stream() - .anyMatch(m -> caseSensitive ? m.getName().matches(methodName) - : m.getName().toLowerCase().matches(methodName.toLowerCase())), - "No method " + methodName); - } - - public String getSourceCode(Class<?> clazz) throws URISyntaxException, IOException { - URL myClassUrl = StructureHelper.class.getResource(this.getClass().getSimpleName() + ".class"); - Path classRoot = Paths.get(myClassUrl.toURI()); - while (!"test-classes".equals(classRoot.getFileName().toString()) - && !"classes".equals(classRoot.getFileName().toString())) { - classRoot = classRoot.getParent(); - } - Path srcRoot = classRoot.getParent().getParent().resolve(Paths.get("src", "main", "java")); - System.out.println("class root: " + classRoot); - Path srcPath = srcRoot.resolve(clazz.getCanonicalName().replace(".", File.separator) + ".java"); - return Files.readString(srcPath); - } - - public Set<String> getNameOfAllClasses() { - Set<String> allClassesName = new TreeSet<>(); - dynamicalyFoundSomeClass(allClassesName); -// allClassesName.addAll(List.of("cz.vsb.fei.lab.App", "lab.Routines", "lab.App", "lab.DrawingThread")); - for (String className : allClassesName) { - try { - Class.forName(className); - break; - } catch (ClassNotFoundException e) { - System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage())); - } - } - for (Package p : Package.getPackages()) { - if (p.getName().startsWith("java.") || p.getName().startsWith("com.") || p.getName().startsWith("jdk.") - || p.getName().startsWith("javafx.") || p.getName().startsWith("org.") - || p.getName().startsWith("sun.") || p.getName().startsWith("javax.") - || p.getName().startsWith("javassist")) { - continue; - } -// System.out.println(p.getName()); - Configuration conf = new ConfigurationBuilder().addScanners(Scanners.SubTypes.filterResultsBy(pc -> true)) - .forPackages(p.getName()); - Reflections reflections = new Reflections(conf); - allClassesName.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> { -// System.out.println(">>> " + c); - return true; - }))); - } - return allClassesName; - } - - private static final List<String> dirsToSkip = List.of("jez04", "META-INF"); - private static final List<String> filesToSkip = List.of("module-info.class"); - - public void dynamicalyFoundSomeClass(Set<String> allClassesName) { - URL myClassUrl = StructureHelper.class.getResource(this.getClass().getSimpleName() + ".class"); - try { - Path classRoot = Paths.get(myClassUrl.toURI()); - while (!"test-classes".equals(classRoot.getFileName().toString()) - && !"classes".equals(classRoot.getFileName().toString())) { - classRoot = classRoot.getParent(); - } - if ("test-classes".equals(classRoot.getFileName().toString())) { - classRoot = classRoot.getParent().resolve("classes"); - } -// System.out.println("class root: " + classRoot); - final Path classRootFinal = classRoot; - Files.walkFileTree(classRoot, new FileVisitor<Path>() { - - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - if (dirsToSkip.contains(dir.getFileName().toString())) { - return FileVisitResult.SKIP_SUBTREE; - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (filesToSkip.contains(file.getFileName().toString())) { - return FileVisitResult.CONTINUE; - } - if (!file.getFileName().toString().endsWith(".class")) { - return FileVisitResult.CONTINUE; - } - if (file.getFileName().toString().contains("$")) { - return FileVisitResult.CONTINUE; - } - String foundClassName = classRootFinal.relativize(file).toString(); - foundClassName = foundClassName.substring(0, foundClassName.length() - 6) - .replace(File.separatorChar, '.'); - addClassAndAllRef(allClassesName, foundClassName); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - }); - } catch (URISyntaxException | IOException e) { - e.printStackTrace(); - } - } - - private void addClassAndAllRef(Set<String> allClassesName, String foundClassName) { - allClassesName.add(foundClassName); - try { - Class<?> foundClass = Class.forName(foundClassName); - List.of(foundClass.getInterfaces()).stream().map(Class::getCanonicalName).forEach(allClassesName::add); - List.of(foundClass.getDeclaredClasses()).stream().map(Class::getCanonicalName).forEach(allClassesName::add); - List.of(foundClass.getDeclaredFields()).stream().map(Field::getType) - .map(clazz -> clazz.isArray() ? clazz.componentType() : clazz) - .filter(Predicate.not(Class::isPrimitive)).map(Class::getCanonicalName) - .forEach(allClassesName::add); - List.of(foundClass.getDeclaredMethods()).stream().map(Method::getReturnType) - .map(clazz -> clazz.isArray() ? clazz.componentType() : clazz) - .filter(Predicate.not(Class::isPrimitive)).map(Class::getCanonicalName) - .forEach(allClassesName::add); - List.of(foundClass.getDeclaredMethods()).stream().flatMap(m -> List.of(m.getParameters()).stream()) - .map(Parameter::getType).map(clazz -> clazz.isArray() ? clazz.componentType() : clazz) - .filter(Predicate.not(Class::isPrimitive)).map(Class::getCanonicalName) - .forEach(allClassesName::add); - List.of(foundClass.getDeclaredMethods()).stream().flatMap(m -> List.of(m.getExceptionTypes()).stream()) - .map(clazz -> clazz.isArray() ? clazz.componentType() : clazz) - .filter(Predicate.not(Class::isPrimitive)).map(Class::getCanonicalName) - .forEach(allClassesName::add); - if (foundClass.getSuperclass() != null) { - allClassesName.add(foundClass.getSuperclass().getCanonicalName()); - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } -} diff --git a/src/test/java/jez04/structure/test/StructureMatcher.java b/src/test/java/jez04/structure/test/StructureMatcher.java deleted file mode 100644 index 6b8bc25..0000000 --- a/src/test/java/jez04/structure/test/StructureMatcher.java +++ /dev/null @@ -1,7 +0,0 @@ -package jez04.structure.test; - -public abstract class StructureMatcher<T> extends org.hamcrest.BaseMatcher<T>{ - - protected StructureHelper structureHelper = StructureHelper.getInstance(); - -} -- GitLab