diff --git a/pom.xml b/pom.xml index 59a8ae7d50bfe9f7fcc8d4978604258f02568df0..b593796e496d9680d1416be0ca5a1ad2619ab19a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,8 +11,32 @@ <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.1-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> @@ -102,7 +126,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/Setup.java b/src/main/java/lab/Setup.java index 6716305b44ee09e7135304617f15a7bd1fe8f07c..9f5e5eddf563503b38f83f0fe2ca3ceebb374f07 100644 --- a/src/main/java/lab/Setup.java +++ b/src/main/java/lab/Setup.java @@ -2,161 +2,46 @@ package lab; import lab.storage.DbConnector; import lab.storage.ScoreStorageInterface; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Builder.Default; +@Getter +@AllArgsConstructor +@lombok.Builder(toBuilder = true) public class Setup { + @Getter private static Setup instance; + @Default private ScoreStorageInterface scoreStorageInterface = new DbConnector(); - private double lochnessMinXPopsition; - private double lochnessMinYPopsition; - private double lochnessMinSpeed; - private double lochnessMaxSpeed; - private int lochnessMultiplier; - private double boatCollisionHeight; - private double boatHitPulseX; - private double boatHitPulseYMin; - private double boatHitPulseYMax; - - private Setup(ScoreStorageInterface scoreStorageInterface, double lochnessMinXPopsition, - double lochnessMinYPopsition, double lochnessMinSpeed, double lochnessMaxSpeed, int lochnessMultiplier, - double boatCollisionHeight, double boatHitPulseX, double boatHitPulseYMin, double boatHitPulseYMax) { - this.scoreStorageInterface = scoreStorageInterface; - this.lochnessMinXPopsition = lochnessMinXPopsition; - this.lochnessMinYPopsition = lochnessMinYPopsition; - this.lochnessMinSpeed = lochnessMinSpeed; - this.lochnessMaxSpeed = lochnessMaxSpeed; - this.lochnessMultiplier = lochnessMultiplier; - this.boatCollisionHeight = boatCollisionHeight; - this.boatHitPulseX = boatHitPulseX; - this.boatHitPulseYMin = boatHitPulseYMin; - this.boatHitPulseYMax = boatHitPulseYMax; - } + @Default + private double lochnessMinXPopsition = 0.5; + @Default + private double lochnessMinYPopsition = 0.5; + @Default + private double lochnessMinSpeed = 50; + @Default + private double lochnessMaxSpeed = 150; + @Default + private int lochnessMultiplier = 1; + @Default + private double boatCollisionHeight = 0.25; + @Default + private double boatHitPulseX = 20; + @Default + private double boatHitPulseYMin = 50; + @Default + private double boatHitPulseYMax = 100; public static void configure(Setup setting) { instance = setting; } - public static Setup getInstance() { - return instance; - } - - public ScoreStorageInterface getScoreStorageInterface() { - return scoreStorageInterface; - } - - public double getBoatCollisionHeight() { - return boatCollisionHeight; - } - - public double getBoatHitPulseX() { - return boatHitPulseX; - } - - public double getBoatHitPulseYMin() { - return boatHitPulseYMin; - } - - public double getBoatHitPulseYMax() { - return boatHitPulseYMax; - } - - public int getLochnessMultiplier() { - return lochnessMultiplier; - } - - public double getLochnessMinXPopsition() { - return lochnessMinXPopsition; - } - - public double getLochnessMinYPopsition() { - return lochnessMinYPopsition; - } - - public double getLochnessMinSpeed() { - return lochnessMinSpeed; - } - - public double getLochnessMaxSpeed() { - return lochnessMaxSpeed; - } - - public static Builder builder() { - return new Builder(); - } - public static Setup getInstanceForHardcoreGame() { return builder().lochnessMaxSpeed(500).lochnessMinSpeed(200).lochnessMultiplier(10).lochnessMinYPopsition(0.1) .build(); } - public static class Builder { - private ScoreStorageInterface scoreStorageInterface = new DbConnector(); - private double lochnessMinXPopsition = 0.5; - private double lochnessMinYPopsition = 0.5; - private double lochnessMinSpeed = 50; - private double lochnessMaxSpeed = 150; - private int lochnessMultiplier = 1; - private double boatCollisionHeight = 0.25; - private double boatHitPulseX = 20; - private double boatHitPulseYMin = 50; - private double boatHitPulseYMax = 100; - - public Builder scoreStorageInterface(ScoreStorageInterface scoreStorageInterface) { - this.scoreStorageInterface = scoreStorageInterface; - return this; - } - - public Builder lochnessMinXPopsition(double lochnessMinXPopsition) { - this.lochnessMinXPopsition = lochnessMinXPopsition; - return this; - } - - public Builder lochnessMinYPopsition(double lochnessMinYPopsition) { - this.lochnessMinYPopsition = lochnessMinYPopsition; - return this; - } - - public Builder lochnessMinSpeed(double lochnessMinSpeed) { - this.lochnessMinSpeed = lochnessMinSpeed; - return this; - } - - public Builder lochnessMaxSpeed(double lochnessMaxSpeed) { - this.lochnessMaxSpeed = lochnessMaxSpeed; - return this; - } - - public Builder lochnessMultiplier(int lochnessMultiplier) { - this.lochnessMultiplier = lochnessMultiplier; - return this; - } - - public Builder boatCollisionHeight(double boatCollisionHeight) { - this.boatCollisionHeight = boatCollisionHeight; - return this; - } - - public Builder boatHitPulseX(double boatHitPulseX) { - this.boatHitPulseX = boatHitPulseX; - return this; - } - - public Builder boatHitPulseYMin(double boatHitPulseYMin) { - this.boatHitPulseYMin = boatHitPulseYMin; - return this; - } - - public Builder boatHitPulseYMax(double boatHitPulseYMax) { - this.boatHitPulseYMax = boatHitPulseYMax; - return this; - } - - public Setup build() { - return new Setup(scoreStorageInterface, lochnessMinXPopsition, lochnessMinYPopsition, lochnessMinSpeed, - lochnessMaxSpeed, lochnessMultiplier, boatCollisionHeight, boatHitPulseX, boatHitPulseYMin, - boatHitPulseYMax); - } - } - } 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 b6c163f020677dbc50e3b203027bbed33382a7e5..950a5578d11e43f02ab497f0db89e74999c86dfe 100644 --- a/src/main/java/lab/game/DeadListener.java +++ b/src/main/java/lab/game/DeadListener.java @@ -1,5 +1,5 @@ package lab.game; public interface DeadListener { - void lochnessDead(); + void lochnessDead(LochNess lochNess); } diff --git a/src/main/java/lab/game/LochNess.java b/src/main/java/lab/game/LochNess.java index a9904f6c550f4359399e904ca2ca71955cde2c1f..07660134b2d4e747fb96527c9fb4f851fa3ac5db 100644 --- a/src/main/java/lab/game/LochNess.java +++ b/src/main/java/lab/game/LochNess.java @@ -91,7 +91,7 @@ public class LochNess extends WorldEntity implements Collisionable { private void fireLochNessDead() { for (DeadListener deadListener : deadListeners) { - deadListener.lochnessDead(); + deadListener.lochnessDead(this); } } } diff --git a/src/main/java/lab/game/Scene.java b/src/main/java/lab/game/Scene.java index edf26a072807a32497058c79565c080d91168f23..a5481b1c9c4237495650669b57b3ced70550a7bc 100644 --- a/src/main/java/lab/game/Scene.java +++ b/src/main/java/lab/game/Scene.java @@ -1,20 +1,25 @@ 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; import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import lab.Setup; +import lombok.extern.log4j.Log4j2; +@Log4j2 public class Scene { private Dimension2D size; private List<DrawableSimulable> sceneEntitites; private List<DrawableSimulable> entititesToAdd = new ArrayList<>(); private List<DrawableSimulable> entititesToRemove = new ArrayList<>(); + private List<LochNessDeadLog> lochNessDeadLogs = new LinkedList<>(); private Boat boat; private Rock rock; @@ -30,10 +35,22 @@ public class Scene { sceneEntitites.add(rock); sceneEntitites.add(boat); for (int i = 0; i < numberOfMonsters * Setup.getInstance().getLochnessMultiplier(); i++) { - sceneEntitites.add(new LochNess(this)); + LochNess lochNess = new LochNess(this); + lochNess.addDeadListener(ln -> lochNessDeadLogs.add(new LochNessDeadLog(LocalDateTime.now(), ln.getPosition()))); + sceneEntitites.add(lochNess); } } + + record LochNessDeadLog(LocalDateTime time, Point2D position) {} + + public void printDeadLog() { + for (LochNessDeadLog lochNessDeadLog : lochNessDeadLogs) { + log.info(lochNessDeadLog); + } + } + + public Dimension2D getSize() { return size; } diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index 40859ad6d454791057a4c21645c11d25bbfc0710..ec45080c6b280cd4e006d86c31bb7b1402b3538e 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -30,7 +30,7 @@ public class App extends Application { public static void main(String[] args) { log.info("Application lauched"); - Setup.configure(Setup.getInstanceForHardcoreGame()); + Setup.configure(Setup.getInstanceForHardcoreGame().toBuilder().boatHitPulseX(-20).build()); launch(args); } @@ -81,6 +81,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 863489ab256f964481f38bc8abc78642ebf1d163..9bf7eceac68170a83783a98afedfc90cb3153247 100644 --- a/src/main/java/lab/gui/GameController.java +++ b/src/main/java/lab/gui/GameController.java @@ -64,13 +64,13 @@ public class GameController { @FXML void changePosition(ActionEvent event) { LochNess lochNess = new LochNess(scene); - lochNess.addDeadListener(() -> log.info("LochNess dead!")); + lochNess.addDeadListener(ln -> log.info("LochNess dead!")); lochNess.addDeadListener(this::addDead); scene.add(lochNess); } - private void addDead() { + private void addDead(LochNess lochNess) { deadLochNessCounter++; updateDeadLabel(); } @@ -131,6 +131,7 @@ public class GameController { public void stop() { timer.stop(); + scene.printDeadLog(); } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 0206796b7e8dd5bf8361b1f7f1c3b18c8c0d145c..cfa87d79b17c05dba67923aa52b2e3aa826eddab 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -4,7 +4,8 @@ module lab04_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 7eb5fb71569deb6664f436b92e6c17a26bec57ce..95bab29ac292caedc816a27dfe31b203bb856070 100644 --- a/src/test/java/jez04/structure/test/ClassStructureTest.java +++ b/src/test/java/jez04/structure/test/ClassStructureTest.java @@ -1,27 +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({ + "Setup,@Getter,1", + "Setup,@.*Builder,1", + "Setup,@.*Default,3" + }) + @ParameterizedTest(name = "useLombokTest in {1} annotation {2}") + void useLombokConfigTest(String className, String text, int count) throws URISyntaxException, ClassNotFoundException { + Class<?> config = helper.getClass(className); + assertThat(config, new SrcContains(text).count(count)); + } + + @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(); - -}