diff --git a/src/main/java/lab/DeadListener.java b/src/main/java/lab/DeadListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a180021d22ecdf365ccc787a085cabfd2f17b93
--- /dev/null
+++ b/src/main/java/lab/DeadListener.java
@@ -0,0 +1,6 @@
+package lab;
+
+@FunctionalInterface
+public interface DeadListener {
+ void monsterDead();
+}
diff --git a/src/main/java/lab/DrawableSimulable.java b/src/main/java/lab/DrawableSimulable.java
index d5b5d45871e5124a9aa526115a50d5e2e64fb401..f4faccac252d8f76a835f0976a675c26844dc843 100644
--- a/src/main/java/lab/DrawableSimulable.java
+++ b/src/main/java/lab/DrawableSimulable.java
@@ -6,4 +6,5 @@ public interface DrawableSimulable {
void draw(GraphicsContext gc);
void simulate(double deltaT);
+ int getZIndex();
}
diff --git a/src/main/java/lab/GameController.java b/src/main/java/lab/GameController.java
index 595ea3489a30cb4408f7ae82315ae11a703f4aa2..e14b4906ca61de4666224593e5fc19f482dd01f1 100644
--- a/src/main/java/lab/GameController.java
+++ b/src/main/java/lab/GameController.java
@@ -16,52 +16,64 @@ public class GameController {
@FXML
private Slider angle;
-
- @FXML
- private Canvas canvas;
-
- @FXML
- private Slider speed;
-
- @FXML
- private Label playerName;
-
- @FXML
- void spawn(ActionEvent event) {
- level.getPlayer().spawn();
-
- }
-
- @FXML
- void initialize() {
- assert angle != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'.";
- assert canvas != null : "fx:id=\"canvas\" was not injected: check your FXML file 'gameWindow.fxml'.";
- assert speed != null : "fx:id=\"speed\" was not injected: check your FXML file 'gameWindow.fxml'.";
- angle.valueProperty().addListener(new ChangeListener<Number>() {
- @Override
- public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
- level.getPlayer().setAngle(newValue.doubleValue());
- }
- });
- speed.valueProperty().addListener(new ChangeListener<Number>() {
- @Override
- public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
- level.getPlayer().setSpeed(newValue.doubleValue());
- }
- });
-
- }
-
- public void startGame(String name, int numberOfMonsters) {
- playerName.setText(name);
- level = new Level(canvas.getWidth(), canvas.getHeight(), numberOfMonsters);
+
+ @FXML
+ private Canvas canvas;
+
+ @FXML
+ private Slider speed;
+
+ @FXML
+ private Label playerName;
+ private int deadCount;
+
+ @FXML
+ void spawn(ActionEvent event) {
+// level.getPlayer().spawn();
+ Monster monster = new Monster(level);
+ monster.addDeadListener(new MujListener());
+ monster.addDeadListener(new Dead());
+ monster.addDeadListener(() -> System.out.println("another lambda dead"));
+ monster.addDeadListener(this::updateDeadLabel);
+ level.add(monster);
+
+ }
+
+ private void updateDeadLabel() {
+ deadCount++;
+ playerName.setText(String.format("Deads: %03d", deadCount));
+ }
+
+ @FXML
+ void initialize() {
+ assert angle != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'.";
+ assert canvas != null : "fx:id=\"canvas\" was not injected: check your FXML file 'gameWindow.fxml'.";
+ assert speed != null : "fx:id=\"speed\" was not injected: check your FXML file 'gameWindow.fxml'.";
+ angle.valueProperty()
+ .addListener((observable, oldValue, newValue) -> level.getPlayer().setAngle(newValue.doubleValue()));
+ speed.valueProperty()
+ .addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
+ level.getPlayer().setSpeed(newValue.doubleValue());
+ });
+
+ }
+
+ public void startGame(String name, int numberOfMonsters) {
+ playerName.setText(name);
+ level = new Level(canvas.getWidth(), canvas.getHeight(), numberOfMonsters);
timer = new DrawingThread(canvas, level);
timer.start();
- }
-
+ }
+
public void stop() {
timer.stop();
}
+ private class Dead implements DeadListener {
+ @Override
+ public void monsterDead() {
+ System.out.println("Named dead");
+ }
+ }
}
diff --git a/src/main/java/lab/Level.java b/src/main/java/lab/Level.java
index 07e610b747dd130b9a7525ce677fbd740c0b4b1e..af3bee7f44b47e82d134cb446498fb8412c1a100 100644
--- a/src/main/java/lab/Level.java
+++ b/src/main/java/lab/Level.java
@@ -1,5 +1,9 @@
package lab;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
import javafx.geometry.Dimension2D;
import javafx.geometry.Point2D;
import javafx.scene.canvas.GraphicsContext;
@@ -9,20 +13,22 @@ public class Level {
private double width;
private double height;
- private DrawableSimulable[] entities;
+ private List<DrawableSimulable> entities;
+ private List<DrawableSimulable> entitiesToAdd = new ArrayList<>();
+ private List<DrawableSimulable> entitiesToRemove = new ArrayList<>();
private Player player;
-
+
public Level(double width, double height, int monsterCount) {
this.width = width;
this.height = height;
player = new Player(this, new Point2D(20, 250), new Point2D(100, -20));
- entities = new DrawableSimulable[monsterCount+4];
- entities[0] = new NicerObstacle(this, new Point2D(20, 150));
- entities[1] = new Obstacle(this, new Point2D(300, 200), new Dimension2D(80, 40));
- entities[2] = new Obstacle(this);
- entities[3] = player;
- for (int i = 4; i < entities.length; i++) {
- entities[i] = new Monster(this);
+ entities = new ArrayList<>();
+ entities.add(new NicerObstacle(this, new Point2D(20, 150)));
+ entities.add(new Obstacle(this, new Point2D(300, 200), new Dimension2D(80, 40)));
+ entities.add(new Obstacle(this));
+ entities.add(player);
+ for (int i = 0; i < monsterCount; i++) {
+ entities.add(new Monster(this));
}
}
@@ -38,10 +44,10 @@ public class Level {
for (DrawableSimulable entity : entities) {
entity.simulate(delay);
}
- for (int i = 0; i < entities.length; i++) {
- if (entities[i] instanceof Collisionable c1) {
- for (int j = i + 1; j < entities.length; j++) {
- if (entities[j] instanceof Collisionable c2) {
+ for (int i = 0; i < entities.size(); i++) {
+ if (entities.get(i) instanceof Collisionable c1) {
+ for (int j = i + 1; j < entities.size(); j++) {
+ if (entities.get(j) instanceof Collisionable c2) {
if (c1.intersect(c2.getBoundingBox())) {
c1.hitBy(c2);
c2.hitBy(c1);
@@ -50,6 +56,17 @@ public class Level {
}
}
}
+ entities.removeAll(entitiesToRemove);
+ entities.addAll(entitiesToAdd);
+ entitiesToAdd.clear();
+ entitiesToRemove.clear();
+ entities.sort(Comparator.comparing(DrawableSimulable::getZIndex));
+// entities.sort(new Comparator<DrawableSimulable>() {
+// @Override
+// public int compare(DrawableSimulable o1, DrawableSimulable o2) {
+// return Integer.compare(o1.getZIndex(), o2.getZIndex());
+// }
+// });
}
public double getWidth() {
@@ -63,5 +80,13 @@ public class Level {
public Player getPlayer() {
return player;
}
-
+
+ public void add(DrawableSimulable entity) {
+ entitiesToAdd.add(entity);
+ }
+
+ public void remove(DrawableSimulable entity) {
+ entitiesToRemove.add(entity);
+ }
+
}
diff --git a/src/main/java/lab/Monster.java b/src/main/java/lab/Monster.java
index 220473a0e4f2e105156aff882bc42635cbe0a6d0..64b677ce229b8f5074d2d775d04a8ff4a4e95ee8 100644
--- a/src/main/java/lab/Monster.java
+++ b/src/main/java/lab/Monster.java
@@ -1,7 +1,10 @@
package lab;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Random;
+import javafx.geometry.Dimension2D;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext;
@@ -13,9 +16,10 @@ public class Monster extends WorldEntity implements Collisionable {
private Image image;
private Point2D speed;
+ private List<DeadListener> deadListeners = new ArrayList<>();
public Monster(Level level) {
- super(level, new Point2D(0, 0));
+ super(level, new Point2D(0, 0), 100);
image = new Image(getClass().getResourceAsStream("red-monster.gif"));
position = new Point2D(level.getWidth() * 0.5 + RANDOM.nextDouble(level.getWidth() * 0.5 - image.getWidth()),
RANDOM.nextDouble(level.getHeight()));
@@ -56,9 +60,24 @@ public class Monster extends WorldEntity implements Collisionable {
@Override
public void hitBy(Collisionable another) {
if (another instanceof Player) {
- changeDirection();
+ level.remove(this);
+ level.add(new Obstacle(level, getPosition(), new Dimension2D(60, 30)));
+ fireMonsterDead();
}
}
+ public boolean addDeadListener(DeadListener e) {
+ return deadListeners.add(e);
+ }
+
+ public boolean removeDeadListener(DeadListener o) {
+ return deadListeners.remove(o);
+ }
+
+ public void fireMonsterDead() {
+ for (DeadListener deadListener : deadListeners) {
+ deadListener.monsterDead();
+ }
+ }
}
diff --git a/src/main/java/lab/MujListener.java b/src/main/java/lab/MujListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7ba9fea16d46dd6d75370b2dc63ae91152e2afb
--- /dev/null
+++ b/src/main/java/lab/MujListener.java
@@ -0,0 +1,12 @@
+package lab;
+
+public class MujListener implements DeadListener {
+
+ @Override
+ public void monsterDead() {
+ System.out.println("AAAAhh!!!!");
+
+ }
+
+
+}
diff --git a/src/main/java/lab/Player.java b/src/main/java/lab/Player.java
index 7bbb0706164176e454fff3b329d2d1c1bc4efa03..93577d77259fced24dcdc78825708904bcdfabb6 100644
--- a/src/main/java/lab/Player.java
+++ b/src/main/java/lab/Player.java
@@ -16,7 +16,7 @@ public class Player extends WorldEntity implements Collisionable {
private double angle;
public Player(Level level, Point2D position, Point2D speed) {
- super(level, position);
+ super(level, position, 50);
this.speed = speed;
}
diff --git a/src/main/java/lab/WorldEntity.java b/src/main/java/lab/WorldEntity.java
index cdeebffe0ebfa084f70e09641748a84d761aa995..dd43f7c660d9a960c2f382043ee87a885c4e945c 100644
--- a/src/main/java/lab/WorldEntity.java
+++ b/src/main/java/lab/WorldEntity.java
@@ -7,12 +7,19 @@ public abstract class WorldEntity implements DrawableSimulable{
protected final Level level;
protected Point2D position;
+ private int zIndex;
public WorldEntity(Level level, Point2D position) {
this.level = level;
this.position = position;
+ zIndex = 0;
}
+ public WorldEntity(Level level, Point2D position, int zIndex) {
+ this.level = level;
+ this.position = position;
+ this.zIndex = zIndex;
+ }
@Override
public final void draw(GraphicsContext gc) {
gc.save();
@@ -26,5 +33,9 @@ public abstract class WorldEntity implements DrawableSimulable{
return position;
}
+ public int getZIndex() {
+ return zIndex;
+ }
+
}
diff --git a/src/test/java/jez04/structure/test/ClassStructureTest.java b/src/test/java/jez04/structure/test/ClassStructureTest.java
index aaf98cc9a4d18a9790d65d4b89f57861e52ad67b..03f1244e4262c6040cda0823813d544d2b5cd413 100644
--- a/src/test/java/jez04/structure/test/ClassStructureTest.java
+++ b/src/test/java/jez04/structure/test/ClassStructureTest.java
@@ -3,13 +3,23 @@ package jez04.structure.test;
import static org.junit.jupiter.api.Assertions.assertTrue;
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.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.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -24,197 +34,112 @@ import org.reflections.util.ConfigurationBuilder;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
-import javafx.geometry.Rectangle2D;
-import javafx.scene.canvas.GraphicsContext;
class ClassStructureTest {
- private static final String drawableSimulableName = "DrawableSimulable";
- private static final String collisionableName = "Collisionable";
-
- Set<String> allClasses = getNameOfAllClasses();
+ StructureHelper helper = new StructureHelper();
@Test
void gameControllerExistenceTest() {
- classExist("GameController");
- Class<?> c = getClass("GameController");
- hasPropertyWithAnnotation(c, ".*", FXML.class);
- hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
+ helper.classExist("GameController");
}
+
@Test
void gameControllerFxmlTest() {
- classExist("GameController");
- Class<?> c = getClass("GameController");
- hasPropertyWithAnnotation(c, ".*", FXML.class);
- }
- @Test
- void gameControllerActionEventTest() {
- classExist("GameController");
- Class<?> c = getClass("GameController");
- hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
+ helper.classExist("GameController");
+ Class<?> c = helper.getClass("GameController");
+ helper.hasPropertyWithAnnotation(c, ".*", FXML.class);
}
@Test
- void cannonExistenceTest() {
- classExist("Player");
- }
- @Test
- void cannonExistenceSetAngleTest() {
- classExist("Player");
- Class<?> c = getClass("Player");
- hasMethod(c, "setAngle");
+ void gameControllerActionMethodTest() {
+ helper.classExist("GameController");
+ Class<?> c = helper.getClass("GameController");
+ helper.hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
}
- @Test
- void cannonExistenceSetSpeedTest() {
- classExist("Player");
- Class<?> c = getClass("Player");
- hasMethod(c, "setSpeed");
- }
-
- private void isInterface(Class<?> c) {
- assertTrue(c.isInterface(), c.getName() + " have to be interface.");
- }
-
- private void classExist(String name) {
- assertTrue(allClasses.stream().anyMatch(c -> c.endsWith(name)), "Interface " + name + " not found");
+ @Test
+ void gameControllerLambdasTest() {
+ helper.classExist("GameController");
+ Class<?> c = helper.getClass("GameController");
+ long lamdaCount = helper.countMethodRegexp(c, "lambda\\$.*");
+ long innerClasscount = helper.countClassesRegexp(".*GameController\\$.*");
+ assertTrue(lamdaCount + innerClasscount >= 3,
+ "At least 3 inner classes or lamdas required for GameController but only "
+ + (lamdaCount + innerClasscount) + " found.");
}
- private Class<?> getClass(String name) {
- String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null);
- if (className == null) {
- Assertions.fail("Class " + name + " not found.");
- }
- 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;
- }
+ @Test
+ void deadListenerExistenceTest() {
+ helper.classExist("DeadListener");
}
- private void hasProperty(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array) {
- List<Field> fields = Arrays.asList(classDef.getDeclaredFields());
- assertTrue(fields.stream().anyMatch(f -> {
- if (f.getName().matches(propertyNameRegexp)) {
- if (array) {
- return f.getType().isArray() && f.getType().getComponentType().equals(type);
- } else {
- return f.getType().equals(type);
- }
- }
- return false;
- }), "No field " + propertyNameRegexp + " of type " + type.getName() + " (is array " + array + ") in class "
- + classDef.getName());
+ @Test
+ void deadListenerEventMethodTest() {
+ helper.classExist("DeadListener");
+ Class<?> c = helper.getClass("DeadListener");
+ helper.hasMethod(c, "monsterDead");
}
- private void hasPropertyWithAnnotation(Class<?> classDef, String propertyNameRegexp, Class<?> annotation) {
- List<Field> fields = Arrays.asList(classDef.getDeclaredFields());
- assertTrue(
- fields.stream().filter(f -> f.getName().matches(propertyNameRegexp))
- .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());
+ @Test
+ void sceneCollectionTest() {
+ helper.classExist("Level");
+ Class<?> c = helper.getClass("Level");
+ long collectionCount = Arrays.asList(c.getDeclaredFields()).stream()
+ .filter(f -> Collection.class.isAssignableFrom(f.getType())).count();
+ assertTrue(collectionCount >= 3, "lab.Scene require atleast 3 filed of type/subtype Collection, but only "
+ + collectionCount + " found.");
}
- private void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType) {
- List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
- assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
- assertTrue(
- methods.stream().filter(m -> m.getName().contains(methodName))
- .anyMatch(m -> m.getReturnType().equals(returnType)),
- "Method " + methodName + " not return " + returnType.getName());
+ @Test
+ void sceneMethodAddTest() {
+ helper.classExist("Level");
+ Class<?> c = helper.getClass("Level");
+ helper.hasMethod(c, "add", void.class, helper.getClass("DrawableSimulable"));
+ ;
}
- private void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, Class<?>... params) {
- List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
- assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
- assertTrue(
- methods.stream().filter(m -> m.getName().contains(methodName))
- .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(", ")));
+ @Test
+ void levelMethodRemoveTest() {
+ helper.classExist("Level");
+ Class<?> c = helper.getClass("Level");
+ helper.hasMethod(c, "remove", void.class, helper.getClass("DrawableSimulable"));
+ ;
}
- private void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType, Class<?>... params) {
- List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
- assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)), "No method " + methodNameRegexp);
- assertTrue(
- methods.stream().filter(m -> m.getName().matches(methodNameRegexp))
- .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(", ")));
- }
- private void hasMethod(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName,
- Class<?> returnType, Class<?>... params) {
- List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
- assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
- assertTrue(
- methods.stream().filter(m -> m.getName().contains(methodName))
- .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(", ")));
+ @Test
+ void monsterMethodAddTest() {
+ helper.classExist("Monster");
+ Class<?> c = helper.getClass("Monster");
+ helper.hasMethod(c, "addDeadListener");
}
- private 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(", ")));
+ @Test
+ void monsterMethodRemoveTest() {
+ helper.classExist("Monster");
+ Class<?> c = helper.getClass("Monster");
+ Class<?> l = helper.getClass("DeadListener");
+ helper.hasMethodRegexp(c, "remove.*", List.of(void.class, boolean.class), l);
}
- private void hasExtends(Class<?> clazz, String parentName) {
- Class<?> parent = getClass(parentName);
- assertTrue(clazz.getSuperclass().equals(parent),
- "Class " + clazz.getName() + " not extends class " + parentName);
+ @Test
+ void monsterMethodFireTest() {
+ helper.classExist("Monster");
+ Class<?> c = helper.getClass("Monster");
+ assertTrue(helper.countMethodRegexp(c, "fire.*") > 0, "Method fire.* in LochNess not found.");
}
- private void hasMethod(Class<?> interfaceDef, String methodName) {
- List<Method> methods = Arrays.asList(interfaceDef.getMethods());
- assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
+ @Test
+ void zIndexMethodTest() {
+ helper.classExist("DrawableSimulable");
+ Class<?> c = helper.getClass("DrawableSimulable");
+ helper.hasMethodRegexp(c, "get[zZ][iI]ndex", int.class, new Class[0]);
}
- private Set<String> getNameOfAllClasses() {
- List<String> initClassesName = Arrays.asList("lab.Routines", "lab.App", "lab.DrawingThread");
- for (String className : initClassesName) {
- try {
- Class.forName(className);
- } catch (ClassNotFoundException e) {
- System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage()));
- }
- }
- Set<String> allClasses = new HashSet<>();
- 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);
- allClasses.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> {
- System.out.println(c);
- return true;
- })));
- }
- return allClasses;
+ @Test
+ void zIndexFieldTest() {
+ helper.classExist("WorldEntity");
+ Class<?> c = helper.getClass("WorldEntity");
+ helper.hasProperty(c, "[zZ][iI]ndex", int.class, false);
}
}
diff --git a/src/test/java/jez04/structure/test/StructureHelper.java b/src/test/java/jez04/structure/test/StructureHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa10c81e0b4ccbc5d8bd405731e00501a30f8c27
--- /dev/null
+++ b/src/test/java/jez04/structure/test/StructureHelper.java
@@ -0,0 +1,272 @@
+package jez04.structure.test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+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.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+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 {
+
+ Set<String> allClasses = getNameOfAllClasses();
+
+ public void isInterface(Class<?> c) {
+ assertTrue(c.isInterface(), c.getName() + " have to be interface.");
+ }
+
+ public void classExist(String name) {
+ assertTrue(allClasses.stream().anyMatch(c -> c.endsWith(name)), "Class/Interface " + name + " not found");
+ }
+
+ public Class<?> getClass(String name) {
+ String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null);
+ if (className == null) {
+ Assertions.fail("Class " + name + " not found.");
+ }
+ 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 void hasProperty(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array) {
+ List<Field> fields = Arrays.asList(classDef.getDeclaredFields());
+ assertTrue(fields.stream().anyMatch(f -> {
+ if (f.getName().matches(propertyNameRegexp)) {
+ if (array) {
+ return f.getType().isArray() && f.getType().getComponentType().equals(type);
+ } else {
+ return f.getType().equals(type);
+ }
+ }
+ return false;
+ }), "No field " + propertyNameRegexp + " of type " + type.getName() + " (is array " + array + ") in class "
+ + classDef.getName());
+ }
+
+ public void hasPropertyWithAnnotation(Class<?> classDef, String propertyNameRegexp, Class<?> annotation) {
+ List<Field> fields = Arrays.asList(classDef.getDeclaredFields());
+ assertTrue(
+ fields.stream().filter(f -> f.getName().matches(propertyNameRegexp))
+ .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) {
+ List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
+ assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
+ assertTrue(
+ methods.stream().filter(m -> m.getName().contains(methodName))
+ .anyMatch(m -> m.getReturnType().equals(returnType)),
+ "Method " + methodName + " not return " + returnType.getName());
+ }
+
+ public void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, Class<?>... params) {
+ List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
+ assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
+ assertTrue(
+ methods.stream().filter(m -> m.getName().contains(methodName))
+ .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 long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp) {
+ List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
+ return methods.stream().filter(m -> m.getName().matches(methodNameRegexp)).count();
+ }
+ public long countClassesRegexp(String classNameRegexp) {
+ return getNameOfAllClasses().stream().filter(className -> className.matches(classNameRegexp)).count();
+ }
+
+ public void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType,
+ Class<?>... params) {
+ List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
+ assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)),
+ "No method " + methodNameRegexp);
+ assertTrue(
+ methods.stream().filter(
+ m ->
+ m.getName().matches(methodNameRegexp))
+ .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 void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Collection<Class<?>> returnTypeOnOf,
+ Class<?>... params) {
+ List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
+ assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)),
+ "No method " + methodNameRegexp);
+ assertTrue(
+ methods.stream().filter(
+ m ->
+ m.getName().matches(methodNameRegexp))
+ .filter(
+ m ->
+ returnTypeOnOf.contains(m.getReturnType()))
+ .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 void hasMethod(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName,
+ Class<?> returnType, Class<?>... params) {
+ List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
+ assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
+ assertTrue(
+ methods.stream().filter(m -> m.getName().contains(methodName))
+ .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 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 hasMethod(Class<?> interfaceDef, String methodName) {
+ List<Method> methods = Arrays.asList(interfaceDef.getMethods());
+ assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
+ }
+
+ public Set<String> getNameOfAllClasses() {
+ List<String> initClassesName = new ArrayList<>();
+ dynamicaliFoundSomeClass(initClassesName);
+ initClassesName.addAll(List.of("lab.Routines", "lab.App", "lab.DrawingThread"));
+ for (String className : initClassesName) {
+ try {
+ Class.forName(className);
+ break;
+ } catch (ClassNotFoundException e) {
+ System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage()));
+ }
+ }
+ Set<String> allClasses = new HashSet<>();
+ 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);
+ allClasses.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> {
+ System.out.println(c);
+ return true;
+ })));
+ }
+ for (String string : allClasses) {
+ System.out.println(string);
+ }
+ return allClasses;
+ }
+
+ public void dynamicaliFoundSomeClass(List<String> initClassesName) {
+ URL myClassUrl = StructureHelper.class.getResource("ClassStructureTest.class");
+ myClassUrl.getFile();
+ try {
+ Path classRoot = Paths.get(myClassUrl.toURI()).getParent().getParent().getParent().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 (List.of("jez04", "META-INF").contains(dir.getFileName().toString())) {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ System.out.println("VISIT: " + file);
+ if ("module-info.class".equals(file.getFileName().toString())) {
+ return FileVisitResult.CONTINUE;
+ }
+ if (!file.getFileName().toString().endsWith(".class")) {
+ return FileVisitResult.CONTINUE;
+ }
+ String foundClassName = classRootFinal.relativize(file).toString();
+ foundClassName = foundClassName.substring(0, foundClassName.length() - 6)
+ .replace(File.separatorChar, '.');
+ initClassesName.add(foundClassName);
+ return FileVisitResult.TERMINATE;
+ }
+
+ @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();
+ }
+ }
+}