Skip to content
Snippets Groups Projects
Commit 9d204cdd authored by jez04's avatar jez04
Browse files

feat: :tada: solution lab07

parent f23e74f9
Branches
No related merge requests found
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>vsb-cs-java1</groupId> <groupId>vsb-cs-java1</groupId>
<artifactId>lab05v1</artifactId> <artifactId>lab07v1</artifactId>
<version>0.0.1-SNAPHOST</version> <version>0.0.1-SNAPHOST</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
...@@ -54,4 +54,16 @@ ...@@ -54,4 +54,16 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<failOnError>false</failOnError>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>
...@@ -15,6 +15,9 @@ import javafx.stage.WindowEvent; ...@@ -15,6 +15,9 @@ import javafx.stage.WindowEvent;
*/ */
public class App extends Application { public class App extends Application {
static {
System.out.println("aaa");
}
private GameController gameController; private GameController gameController;
public static void main(String[] args) { public static void main(String[] args) {
launch(args); launch(args);
......
package lab; package lab;
import java.util.ArrayList;
import java.util.List;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D; import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
...@@ -11,6 +14,8 @@ public class BulletAnimated extends Bullet { ...@@ -11,6 +14,8 @@ public class BulletAnimated extends Bullet {
private final Point2D initVelocity; private final Point2D initVelocity;
private Cannon cannon; private Cannon cannon;
private Image image = new Image(this.getClass().getResourceAsStream("fireball-transparent.gif")); private Image image = new Image(this.getClass().getResourceAsStream("fireball-transparent.gif"));
private List<HitListener> hitListeners =
new ArrayList<>();
public BulletAnimated(World world, Cannon cannon, Point2D position, Point2D velocity, Point2D acceleration) { public BulletAnimated(World world, Cannon cannon, Point2D position, Point2D velocity, Point2D acceleration) {
super(world, position, velocity, acceleration); super(world, position, velocity, acceleration);
...@@ -27,7 +32,8 @@ public class BulletAnimated extends Bullet { ...@@ -27,7 +32,8 @@ public class BulletAnimated extends Bullet {
@Override @Override
public void hitBy(Collisionable another) { public void hitBy(Collisionable another) {
if (another instanceof Ufo) { if (another instanceof Ufo) {
reload(); world.remove(this);
fireUfoDestroyed();
} }
} }
...@@ -35,5 +41,19 @@ public class BulletAnimated extends Bullet { ...@@ -35,5 +41,19 @@ public class BulletAnimated extends Bullet {
position = cannon.getPosition(); position = cannon.getPosition();
velocity = new Point2D(0, 0); velocity = new Point2D(0, 0);
} }
public boolean addHitListener(HitListener e) {
return hitListeners.add(e);
}
public boolean removeHitListener(HitListener o) {
return hitListeners.remove(o);
}
private void fireUfoDestroyed() {
for (HitListener hitListener : hitListeners) {
hitListener.ufoDestroyed();
}
}
} }
\ No newline at end of file
package lab; package lab;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.scene.canvas.Canvas; import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label;
import javafx.scene.control.Slider; import javafx.scene.control.Slider;
public class GameController { public class GameController {
...@@ -21,18 +20,37 @@ public class GameController { ...@@ -21,18 +20,37 @@ public class GameController {
private DrawingThread timer; private DrawingThread timer;
@FXML
private Label hits;
private int hitcount = 0;
@FXML @FXML
void fire(ActionEvent event) { void fire(ActionEvent event) {
double angle = timer.getWorld().getCannon().getAngle(); double angle = timer.getWorld().getCannon().getAngle();
double angleRad = Math.toRadians(angle); double angleRad = Math.toRadians(angle);
double speedValue = speed.getValue(); double speedValue = speed.getValue();
timer.getWorld().getBulletAnimated().reload();
Point2D velocity = new Point2D( Point2D velocity = new Point2D(
Math.cos(angleRad)*speedValue, Math.cos(angleRad)*speedValue,
Math.sin(angleRad)*speedValue); Math.sin(angleRad)*speedValue);
timer.getWorld().getBulletAnimated().setVelocity(velocity); BulletAnimated bulletAnimated = new BulletAnimated(
timer.getWorld(),
timer.getWorld().getCannon(),
timer.getWorld().getCannon().getPosition(),
velocity, World.GRAVITY);
timer.getWorld().add(bulletAnimated);
bulletAnimated.addHitListener(this::increaseHits);
bulletAnimated.addHitListener(
() -> System.out.println("au!!!!"));
} }
private void updateHits() {
hits.setText(String.format("Hit count: %03d", hitcount));
}
private void increaseHits() {
hitcount++;
updateHits();
}
@FXML @FXML
void initialize() { void initialize() {
assert angle != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'."; assert angle != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'.";
...@@ -40,12 +58,9 @@ public class GameController { ...@@ -40,12 +58,9 @@ public class GameController {
assert speed != null : "fx:id=\"speed\" was not injected: check your FXML file 'gameWindow.fxml'."; assert speed != null : "fx:id=\"speed\" was not injected: check your FXML file 'gameWindow.fxml'.";
timer = new DrawingThread(canvas); timer = new DrawingThread(canvas);
timer.start(); timer.start();
angle.valueProperty().addListener(new ChangeListener<Number>() { angle.valueProperty().addListener(
@Override (observable, oldValue, newValue) ->
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) { timer.getWorld().getCannon().setAngle(newValue.doubleValue()));
timer.getWorld().getCannon().setAngle(newValue.doubleValue());
}
});
} }
public void stop() { public void stop() {
......
package lab;
@FunctionalInterface
public interface HitListener {
void ufoDestroyed();
}
...@@ -54,7 +54,7 @@ public class Ufo extends WorldEntity implements Collisionable { ...@@ -54,7 +54,7 @@ public class Ufo extends WorldEntity implements Collisionable {
@Override @Override
public void hitBy(Collisionable another) { public void hitBy(Collisionable another) {
if(another instanceof BulletAnimated || another instanceof Bullet) { if(another instanceof BulletAnimated || another instanceof Bullet) {
changeDirection(); world.remove(this);
} }
} }
} }
package lab; package lab;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
public class World { public class World {
public static final Point2D GRAVITY = new Point2D(0, 9.81);
private final double width; private final double width;
private final double height; private final double height;
private DrawableSimulable[] entities; private List<DrawableSimulable> entities;
private Collection<DrawableSimulable> entitiesToRemove = new LinkedList<DrawableSimulable>();
private Collection<DrawableSimulable> entitiesToAdd = new LinkedList<DrawableSimulable>();
private Cannon cannon; private Cannon cannon;
private BulletAnimated bulletAnimated; // private BulletAnimated bulletAnimated;
public World(double width, double height) { public World(double width, double height) {
this.width = width; this.width = width;
this.height = height; this.height = height;
entities = new DrawableSimulable[8]; entities = new ArrayList<>();
cannon = new Cannon(this, new Point2D(0, height - 20), -45); cannon = new Cannon(this, new Point2D(0, height - 20), -45);
bulletAnimated = new BulletAnimated(this, cannon, new Point2D(0, height), new Point2D(50, -80), // bulletAnimated = new BulletAnimated(this, cannon, new Point2D(0, height), new Point2D(50, -80),
new Point2D(0, 9.81)); // GRAVITY);
entities[0] = cannon; entities.add(cannon);
entities[1] = new Bullet(this, new Point2D(0, height), new Point2D(30, -30), new Point2D(0, 9.81)); entities.add(new Bullet(this, new Point2D(0, height), new Point2D(30, -30), new Point2D(0, 9.81)));
entities[2] = bulletAnimated; // entities.add(bulletAnimated);
for (int i = 3; i < entities.length; i++) { for (int i = 0; i < 3; i++) {
entities[i] = new Ufo(this); entities.add(new Ufo(this));
} }
} }
...@@ -44,10 +52,10 @@ public class World { ...@@ -44,10 +52,10 @@ public class World {
for (DrawableSimulable entity : entities) { for (DrawableSimulable entity : entities) {
entity.simulate(deltaT); entity.simulate(deltaT);
} }
for (int i = 0; i < entities.length; i++) { for (int i = 0; i < entities.size(); i++) {
if (entities[i] instanceof Collisionable c1) { if (entities.get(i) instanceof Collisionable c1) {
for (int j = i + 1; j < entities.length; j++) { for (int j = i + 1; j < entities.size(); j++) {
if (entities[j] instanceof Collisionable c2) { if (entities.get(j) instanceof Collisionable c2) {
if (c1.intersect(c2.getBoundingBox())) { if (c1.intersect(c2.getBoundingBox())) {
c1.hitBy(c2); c1.hitBy(c2);
c2.hitBy(c1); c2.hitBy(c1);
...@@ -56,11 +64,23 @@ public class World { ...@@ -56,11 +64,23 @@ public class World {
} }
} }
} }
entities.removeAll(entitiesToRemove);
entities.addAll(entitiesToAdd);
entitiesToAdd.clear();
entitiesToRemove.clear();
} }
public double getWidth() { public double getWidth() {
return width; return width;
} }
public void add(DrawableSimulable entity) {
entitiesToAdd.add(entity);
}
public void remove(DrawableSimulable entity) {
entitiesToRemove.add(entity);
}
public double getHeight() { public double getHeight() {
return height; return height;
...@@ -70,8 +90,8 @@ public class World { ...@@ -70,8 +90,8 @@ public class World {
return cannon; return cannon;
} }
public BulletAnimated getBulletAnimated() { // public BulletAnimated getBulletAnimated() {
return bulletAnimated; // return bulletAnimated;
} // }
//
} }
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
<?import javafx.scene.Cursor?> <?import javafx.scene.Cursor?>
<?import javafx.scene.canvas.Canvas?> <?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?> <?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
...@@ -33,10 +34,13 @@ ...@@ -33,10 +34,13 @@
</HBox> </HBox>
</bottom> </bottom>
<center> <center>
<Canvas fx:id="canvas" height="287.0" width="582.0" BorderPane.alignment="CENTER"> <Canvas fx:id="canvas" height="306.0" width="582.0" BorderPane.alignment="CENTER">
<BorderPane.margin> <BorderPane.margin>
<Insets /> <Insets />
</BorderPane.margin> </BorderPane.margin>
</Canvas> </Canvas>
</center> </center>
<top>
<Label fx:id="hits" text="Hit count: 0" textAlignment="CENTER" BorderPane.alignment="CENTER" />
</top>
</BorderPane> </BorderPane>
src/main/resources/lab/scenery.gif

3.75 MiB

...@@ -3,13 +3,23 @@ package jez04.structure.test; ...@@ -3,13 +3,23 @@ package jez04.structure.test;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
...@@ -24,191 +34,100 @@ import org.reflections.util.ConfigurationBuilder; ...@@ -24,191 +34,100 @@ import org.reflections.util.ConfigurationBuilder;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext;
class ClassStructureTest { class ClassStructureTest {
private static final String drawableSimulableName = "DrawableSimulable"; StructureHelper helper = new StructureHelper();
private static final String collisionableName = "Collisionable";
Set<String> allClasses = getNameOfAllClasses();
@Test @Test
void gameControllerExistenceTest() { void gameControllerExistenceTest() {
classExist("GameController"); helper.classExist("GameController");
Class<?> c = getClass("GameController");
hasPropertyWithAnnotation(c, ".*", FXML.class);
hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
} }
@Test @Test
void gameControllerFxmlTest() { void gameControllerFxmlTest() {
classExist("GameController"); helper.classExist("GameController");
Class<?> c = getClass("GameController"); Class<?> c = helper.getClass("GameController");
hasPropertyWithAnnotation(c, ".*", FXML.class); helper.hasPropertyWithAnnotation(c, ".*", FXML.class);
}
@Test
void gameControllerActionEventTest() {
classExist("GameController");
Class<?> c = getClass("GameController");
hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
} }
@Test @Test
void cannonExistenceTest() { void gameControllerActionMethodTest() {
classExist("Cannon"); helper.classExist("GameController");
} Class<?> c = helper.getClass("GameController");
@Test helper.hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
void cannonExistenceSetAngleTest() {
classExist("Cannon");
Class<?> c = getClass("Cannon");
hasMethod(c, "setAngle");
}
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");
} }
private Class<?> getClass(String name) { @Test
String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null); void gameControllerLambdasTest() {
if (className == null) { helper.classExist("GameController");
Assertions.fail("Class " + name + " not found."); Class<?> c = helper.getClass("GameController");
} long lamdaCount = helper.countMethodRegexp(c, "lambda\\$.*");
try { long innerClasscount = helper.countClassesRegexp(".*GameController\\$.*");
return Class.forName(className); assertTrue(lamdaCount + innerClasscount >= 2,
} catch (ClassNotFoundException e) { "At least 2 inner classes or lamdas required for GameController but only "
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + (lamdaCount + innerClasscount) + " found.");
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;
}
} }
private void hasProperty(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array) { @Test
List<Field> fields = Arrays.asList(classDef.getDeclaredFields()); void hitListenerExistenceTest() {
assertTrue(fields.stream().anyMatch(f -> { helper.classExist("HitListener");
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());
} }
private void hasPropertyWithAnnotation(Class<?> classDef, String propertyNameRegexp, Class<?> annotation) { @Test
List<Field> fields = Arrays.asList(classDef.getDeclaredFields()); void hitListenerEventMethodTest() {
assertTrue( helper.classExist("HitListener");
fields.stream().filter(f -> f.getName().matches(propertyNameRegexp)) Class<?> c = helper.getClass("HitListener");
.flatMap(f -> Arrays.asList( helper.hasMethod(c, "ufoDestroyed");
f.getAnnotations()).stream()).map(a -> a.annotationType()).anyMatch(a ->
a.equals(annotation)),
"No field " + propertyNameRegexp + " with annotation " + annotation.getName() + " in class "
+ classDef.getName());
} }
private void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType) { @Test
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); void sceneCollectionTest() {
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName); helper.classExist("World");
assertTrue( Class<?> c = helper.getClass("World");
methods.stream().filter(m -> m.getName().contains(methodName)) long collectionCount = Arrays.asList(c.getDeclaredFields()).stream()
.anyMatch(m -> m.getReturnType().equals(returnType)), .filter(f -> Collection.class.isAssignableFrom(f.getType())).count();
"Method " + methodName + " not return " + returnType.getName()); 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, Class<?>... params) { @Test
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); void worldMethodAddTest() {
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName); helper.classExist("World");
assertTrue( Class<?> c = helper.getClass("World");
methods.stream().filter(m -> m.getName().contains(methodName)) helper.hasMethod(c, "add", void.class, helper.getClass("DrawableSimulable"));
.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(", ")));
} }
private void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType, Class<?>... params) { @Test
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); void worldMethodRemoveTest() {
assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)), "No method " + methodNameRegexp); helper.classExist("World");
assertTrue( Class<?> c = helper.getClass("World");
methods.stream().filter(m -> m.getName().matches(methodNameRegexp)) helper.hasMethod(c, "remove", void.class, helper.getClass("DrawableSimulable"));
.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(", ")));
} }
private void hasImplements(Class<?> clazz, String... interfaceNames) { @Test
List<Class<?>> interfaces = new ArrayList<>(); void bulletAnimatedMethodAddTest() {
Arrays.asList(interfaceNames).stream().map(name -> getClass(name)).forEach(c -> interfaces.add(c)); helper.classExist("BulletAnimated");
assertTrue(Arrays.asList(clazz.getInterfaces()).containsAll(interfaces), "Class not implements all interfaces:" Class<?> c = helper.getClass("BulletAnimated");
+ interfaces.stream().map(Class::getName).collect(Collectors.joining(", "))); Class<?> l = helper.getClass("HitListener");
helper.hasMethodRegexp(c, "add.*", List.of(void.class, boolean.class), l);
} }
private void hasExtends(Class<?> clazz, String parentName) { @Test
Class<?> parent = getClass(parentName); void bulletAnimatedMethodRemoveTest() {
assertTrue(clazz.getSuperclass().equals(parent), helper.classExist("Ufo");
"Class " + clazz.getName() + " not extends class " + parentName); Class<?> c = helper.getClass("BulletAnimated");
Class<?> l = helper.getClass("HitListener");
helper.hasMethodRegexp(c, "remove.*", List.of(void.class, boolean.class), l);
} }
private void hasMethod(Class<?> interfaceDef, String methodName) { @Test
List<Method> methods = Arrays.asList(interfaceDef.getMethods()); void bulletAnimatedMethodFireTest() {
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName); helper.classExist("BulletAnimated");
Class<?> c = helper.getClass("BulletAnimated");
assertTrue(helper.countMethodRegexp(c, "fire.*") > 0, "Method fire.* in LochNess not found.");
} }
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;
}
} }
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();
}
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment