diff --git a/pom.xml b/pom.xml index 4a51e6e3c1471f58f9b43319dc26014e9d148ae7..126896849a92dc3c576607714909e86190031fb6 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,33 @@ <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.36</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.0.3-SNAPSHOT,)</version> + <scope>test</scope> + </dependency> + <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> + <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> @@ -70,19 +95,6 @@ <version>5.11.0</version> <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,6 +104,13 @@ <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/Config.java b/src/main/java/lab/Config.java index 0a18ac14467a53af169efc0f07de81e85605ae6d..31ec69ddf7b454af26123c4545d46c16cdd63399 100644 --- a/src/main/java/lab/Config.java +++ b/src/main/java/lab/Config.java @@ -2,138 +2,42 @@ package lab; import lab.storage.DbConnector; import lab.storage.ScoreStorageInterface; +import lombok.AllArgsConstructor; +import lombok.Builder.Default; +import lombok.Getter; +@Getter +@AllArgsConstructor +@lombok.Builder(toBuilder = true) public class Config { + @Getter private static Config instance; - private ScoreStorageInterface scoreStorageInterface; - private double monsterMinXPopsition; - private double monsterMinSpeed; - private double monsterMaxSpeed; - private double obstacleWidth; - private double obstacleHeight; - private double playerStartSpeed; - private int monsterMultiplier; + @Default + private ScoreStorageInterface scoreStorageInterface = new DbConnector(); + @Default + private double monsterMinXPopsition = 0.5; + @Default + private double monsterMinSpeed = 50; + @Default + private double monsterMaxSpeed = 150; + @Default + private double obstacleWidth = 30; + @Default + private double obstacleHeight = 20; + @Default + private double playerStartSpeed = 50; + @Default + private int monsterMultiplier = 1; public static void configure(Config setting) { instance = setting; } - private Config(ScoreStorageInterface scoreStorageInterface, double monsterMinXPopsition, double monsterMinSpeed, - double monsterMaxSpeed, double obstacleWidth, double obstacleHeight, double playerStartSpeed, - int monsterMultiplier) { - super(); - this.scoreStorageInterface = scoreStorageInterface; - this.monsterMinXPopsition = monsterMinXPopsition; - this.monsterMinSpeed = monsterMinSpeed; - this.monsterMaxSpeed = monsterMaxSpeed; - this.obstacleWidth = obstacleWidth; - this.obstacleHeight = obstacleHeight; - this.playerStartSpeed = playerStartSpeed; - this.monsterMultiplier = monsterMultiplier; - } - - public static Config getInstance() { - return instance; - } - - public ScoreStorageInterface getScoreStorageInterface() { - return scoreStorageInterface; - } - - public double getMonsterMinXPopsition() { - return monsterMinXPopsition; - } - - public double getMonsterMinSpeed() { - return monsterMinSpeed; - } - - public double getMonsterMaxSpeed() { - return monsterMaxSpeed; - } - - public double getObstacleHeight() { - return obstacleHeight; - } - - public double getObstacleWidth() { - return obstacleWidth; - } - - public double getPlayerStartSpeed() { - return playerStartSpeed; - } - - public int getMonsterMultiplier() { - return monsterMultiplier; - } - - public static Builder builder() { - return new Builder(); - } - public static Config getInstanceForHardcoreGame() { return builder().monsterMinSpeed(150).monsterMaxSpeed(500).monsterMultiplier(5).monsterMinXPopsition(0.2) .build(); } - public static class Builder { - private ScoreStorageInterface scoreStorageInterface = new DbConnector(); - private double monsterMinXPopsition = 0.5; - private double monsterMinSpeed = 50; - private double monsterMaxSpeed = 150; - private double obstacleWidth = 30; - private double obstacleHeight = 20; - private double playerStartSpeed = 50; - private int monsterMultiplier = 1; - - public Builder scoreStorageInterface(ScoreStorageInterface scoreStorageInterface) { - this.scoreStorageInterface = scoreStorageInterface; - return this; - } - - public Builder monsterMinXPopsition(double monsterMinXPopsition) { - this.monsterMinXPopsition = monsterMinXPopsition; - return this; - } - - public Builder monsterMinSpeed(double monsterMinSpeed) { - this.monsterMinSpeed = monsterMinSpeed; - return this; - } - - public Builder monsterMaxSpeed(double monsterMaxSpeed) { - this.monsterMaxSpeed = monsterMaxSpeed; - return this; - } - - public Builder obstacleWidth(double obstacleWidth) { - this.obstacleWidth = obstacleWidth; - return this; - } - - public Builder obstacleHeight(double obstacleHeight) { - this.obstacleHeight = obstacleHeight; - return this; - } - - public Builder playerStartSpeed(double playerStartSpeed) { - this.playerStartSpeed = playerStartSpeed; - return this; - } - - public Builder monsterMultiplier(int monsterMultiplier) { - this.monsterMultiplier = monsterMultiplier; - return this; - } - - public Config build() { - return new Config(scoreStorageInterface, monsterMinXPopsition, monsterMinSpeed, monsterMaxSpeed, - obstacleWidth, obstacleHeight, playerStartSpeed, monsterMultiplier); - } - - } - } diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java index a9993a9c51be53b7870842a1757836b776292340..71011021a0d6dabdb1ead49426440dab6cbd8797 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/DeadListener.java b/src/main/java/lab/game/DeadListener.java index 8afff386a6bfe0b9b434ae7f4d742105a5a1aa18..afb0cde0dfaa9d17f2019f7b02ca2f11950433ac 100644 --- a/src/main/java/lab/game/DeadListener.java +++ b/src/main/java/lab/game/DeadListener.java @@ -2,5 +2,5 @@ package lab.game; @FunctionalInterface public interface DeadListener { - void monsterDead(); + void monsterDead(Monster monster); } diff --git a/src/main/java/lab/game/Level.java b/src/main/java/lab/game/Level.java index 7b6a9221a52627d44ef73194a4765090dbf93d9b..097818f4b99c9542955677cd2dfb2ed55b7a5d03 100644 --- a/src/main/java/lab/game/Level.java +++ b/src/main/java/lab/game/Level.java @@ -1,7 +1,9 @@ package lab.game; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Comparator; +import java.util.LinkedList; import java.util.List; import javafx.geometry.Dimension2D; @@ -9,7 +11,9 @@ import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import lab.Config; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class Level { private double width; @@ -18,6 +22,7 @@ public class Level { private List<DrawableSimulable> entitiesToAdd = new ArrayList<>(); private List<DrawableSimulable> entitiesToRemove = new ArrayList<>(); private Player player; + private List<MonsterDeadLog> deadLogs = new LinkedList<>(); public Level(double width, double height, int monsterCount) { this.width = width; @@ -29,10 +34,19 @@ public class Level { entities.add(new Obstacle(this)); entities.add(player); for (int i = 0; i < monsterCount*Config.getInstance().getMonsterMultiplier(); i++) { - entities.add(new Monster(this)); + Monster monster = new Monster(this); + monster.addDeadListener(m -> deadLogs.add(new MonsterDeadLog(LocalDateTime.now(), m.getPosition()))); + entities.add(monster); } } + + record MonsterDeadLog(LocalDateTime time, Point2D position) {} + public void printDeadLog() { + for (MonsterDeadLog monsterDeadLog : deadLogs) { + log.info(monsterDeadLog); + } + } public void draw(GraphicsContext gc) { gc.setFill(Color.WHITE); gc.clearRect(0, 0, width, height); diff --git a/src/main/java/lab/game/Monster.java b/src/main/java/lab/game/Monster.java index 345db3133ff2013ad21ca3d04ff56cd456f7ac2d..d8955d65c58ef6e5aa0cc242c6bd24b7261672cf 100644 --- a/src/main/java/lab/game/Monster.java +++ b/src/main/java/lab/game/Monster.java @@ -87,7 +87,7 @@ public class Monster extends WorldEntity implements Collisionable { public void fireMonsterDead() { for (DeadListener deadListener : deadListeners) { - deadListener.monsterDead(); + deadListener.monsterDead(this); } } } diff --git a/src/main/java/lab/game/MujListener.java b/src/main/java/lab/game/MujListener.java index e506f3fe4706ac6f49d9748190a87e0b9b8213d0..d6392759fc0ad555bbce6df193b797d534ecee56 100644 --- a/src/main/java/lab/game/MujListener.java +++ b/src/main/java/lab/game/MujListener.java @@ -3,7 +3,7 @@ package lab.game; public class MujListener implements DeadListener { @Override - public void monsterDead() { + public void monsterDead(Monster monster) { System.out.println("AAAAhh!!!!"); } diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index 270f55187013d85a9bbc7812f2325845be0d59d0..02d634aff8b9f0d456dea935c6145d80de463942 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -80,6 +80,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 fde1322c0cfd3c1d7bd889c85c76d04402e38cae..85d85eceeb79d577b312a70c83d490b65c31cfd3 100644 --- a/src/main/java/lab/gui/GameController.java +++ b/src/main/java/lab/gui/GameController.java @@ -1,8 +1,5 @@ package lab.gui; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import javafx.animation.AnimationTimer; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; @@ -15,11 +12,11 @@ import lab.game.DrawingThread; import lab.game.Level; import lab.game.Monster; import lab.game.MujListener; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class GameController { - private static Logger log = LogManager.getLogger(GameController.class); - private AnimationTimer timer; private Level level; @@ -42,13 +39,13 @@ public class GameController { Monster monster = new Monster(level); monster.addDeadListener(new MujListener()); monster.addDeadListener(new Dead()); - monster.addDeadListener(() -> System.out.println("another lambda dead")); + monster.addDeadListener(m -> log.info("another lambda dead")); monster.addDeadListener(this::updateDeadLabel); level.add(monster); } - private void updateDeadLabel() { + private void updateDeadLabel(Monster monster) { deadCount++; playerName.setText(String.format("Deads: %03d", deadCount)); } @@ -77,13 +74,14 @@ public class GameController { } public void stop() { + level.printDeadLog(); timer.stop(); } private class Dead implements DeadListener { @Override - public void monsterDead() { - System.out.println("Named dead"); + public void monsterDead(Monster monster) { + log.info("Named dead"); } } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 75517d2cb9c0ac2380899c7faf60e5c6d1fa0c85..3f19883afeb9b244845aa41b499a0f511f756af2 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/test/java/jez04/structure/test/AllOfContinue.java b/src/test/java/jez04/structure/test/AllOfContinue.java deleted file mode 100644 index 8eb250be7bf4933fb898098380bfe3b87cec6ffe..0000000000000000000000000000000000000000 --- 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 7e1f9b78a7f8f5039333470143b91954e77ef9fc..0000000000000000000000000000000000000000 --- 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 bf058e02641b88d0f6de5ee9caf243014676e2b3..e13f549c2d9df2c966235777e0462939d76b59cc 100644 --- a/src/test/java/jez04/structure/test/ClassStructureTest.java +++ b/src/test/java/jez04/structure/test/ClassStructureTest.java @@ -1,28 +1,86 @@ 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 java.util.Objects; +import java.util.stream.Stream; +import org.hamcrest.Matchers; 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.SrcContains; +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({ + "Config,@Getter,1", + "Config,@.*Builder,1", + "Config,@.*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)); + } + + @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)); + + } } 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 5c7952997243af56384183f1ad7b9a784bd82cbb..0000000000000000000000000000000000000000 --- 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 142fec8b77806805f8560a89d83a64d9fb788809..0000000000000000000000000000000000000000 --- 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 0e7098dfaccbfef827f8abe1ea02c5bd09c5d855..0000000000000000000000000000000000000000 --- 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 a202faa8359dd596d8b8ab9fc8dac8426a66967f..0000000000000000000000000000000000000000 --- 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 2abdee29266beb46899bf441eb75b6b8adef861c..0000000000000000000000000000000000000000 --- 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 e7d92772860242e62e7a508e6813cf5d04de06cc..0000000000000000000000000000000000000000 --- 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 4ed7d6c3e0250f75646317233c2f39e74881ec75..0000000000000000000000000000000000000000 --- 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 6ccabb4d3b2e307664acba8933c2ae35cfb83175..0000000000000000000000000000000000000000 --- 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 6b8bc25eb09606250e61ed18e2955a96c02692d1..0000000000000000000000000000000000000000 --- 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(); - -}