From 4dcc5870db5b1b646a81e4b63c968a879d95e8ab Mon Sep 17 00:00:00 2001
From: jez04 <david.jezek@post.cz>
Date: Thu, 28 Nov 2024 00:37:59 +0100
Subject: [PATCH] feta: change project name and update test

---
 pom.xml                                       |  15 +-
 .../structure/test/ClassStructureTest.java    | 149 +++++++++---------
 .../jez04/structure/test/StructureHelper.java |  94 +++++++++--
 3 files changed, 165 insertions(+), 93 deletions(-)

diff --git a/pom.xml b/pom.xml
index 09bb40b..d79e6e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>vsb-cs-java1</groupId>
-	<artifactId>lab07v3</artifactId>
+	<artifactId>lab10v3</artifactId>
 	<version>0.0.1-SNAPHOST</version>
 	<packaging>jar</packaging>
 	<properties>
@@ -22,6 +22,19 @@
 			<artifactId>javafx-fxml</artifactId>
 			<version>23</version>
 		</dependency>
+		<dependency>
+			<groupId>org.openjfx</groupId>
+			<artifactId>javafx-media</artifactId>
+			<version>23</version>
+		</dependency>
+        <dependency>
+            <groupId>org.controlsfx</groupId>
+            <artifactId>controlsfx</artifactId>
+            <version>11.2.1</version>
+        </dependency>
+
+
+
 		<!--
 		https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
 		<dependency>
diff --git a/src/test/java/jez04/structure/test/ClassStructureTest.java b/src/test/java/jez04/structure/test/ClassStructureTest.java
index a1a6b0d..eac5918 100644
--- a/src/test/java/jez04/structure/test/ClassStructureTest.java
+++ b/src/test/java/jez04/structure/test/ClassStructureTest.java
@@ -5,7 +5,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintStream;
+import java.io.Reader;
+import java.io.Writer;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -40,105 +44,100 @@ class ClassStructureTest {
 	StructureHelper helper = new StructureHelper();
 
 	@Test
-	void gameControllerExistenceTest() {
-		helper.classExist("GameController");
+	void detectNioPackageTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().anyMatch(name -> name.contains("java.nio")),
+				"Usage of NIO package not detected.");
 	}
 
 	@Test
-	void gameControllerFxmlTest() {
-		helper.classExist("GameController");
-		Class<?> c = helper.getClass("GameController");
-		helper.hasPropertyWithAnnotation(c, ".*", FXML.class);
+	void detectUsageOfIoPackageTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().anyMatch(name -> name.contains("java.io")),
+				"Usage of java IO package not detected.");
 	}
 
 	@Test
-	void gameControllerActionMethodTest() {
-		helper.classExist("GameController");
-		Class<?> c = helper.getClass("GameController");
-		helper.hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
+	void detectUsageOfPathClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().anyMatch(name -> name.contains("java.nio.file.Path")),
+				"Usage of Path not detected.");
 	}
 
 	@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.");
+	void detectUsageOfFileClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().anyMatch(name -> name.contains("java.nio.file.File")),
+				"Usage of NIO File not detected.");
 	}
 
 	@Test
-	void deadListenerExistenceTest() {
-		helper.classExist("DeadListener");
+	void detectUsageOfInputStreamClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().map(className -> {
+			try {
+				return Class.forName(className);
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+			}
+			return Object.class;
+		}).anyMatch(clazz -> InputStream.class.isAssignableFrom(clazz)), "Usage of InputStream not detected.");
 	}
 
 	@Test
-	void deadListenerEventMethodTest() {
-		helper.classExist("DeadListener");
-		Class<?> c = helper.getClass("DeadListener");
-		helper.hasMethod(c, "lochnessDead");
+	void detectUsageOfReaderClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().map(className -> {
+			try {
+				return Class.forName(className);
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+			}
+			return Object.class;
+		}).anyMatch(clazz -> Reader.class.isAssignableFrom(clazz)), "Usage of Reader not detected.");
 	}
 
 	@Test
-	void sceneCollectionTest() {
-		helper.classExist("lab.Scene");
-		Class<?> c = helper.getClass("lab.Scene");
-		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.");
+	void detectUsageOfOutputStreamClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().map(className -> {
+			try {
+				return Class.forName(className);
+			} catch (Throwable e) {
+				System.out.println(e.getMessage());
+			}
+			return Object.class;
+		}).anyMatch(clazz -> OutputStream.class.isAssignableFrom(clazz)), "Usage of OutputStream not detected.");
 	}
 
 	@Test
-	void sceneMethodAddTest() {
-		helper.classExist("lab.Scene");
-		Class<?> c = helper.getClass("lab.Scene");
-		helper.hasMethod(c, "add", void.class, helper.getClass("DrawableSimulable"));
-		;
+	void detectUsageOfWriterTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().map(className -> {
+			try {
+				return Class.forName(className);
+			} catch (ClassNotFoundException e) {
+				System.out.println(e.getMessage());
+			}
+			return Object.class;
+		}).anyMatch(clazz -> 
+		Writer.class.isAssignableFrom(clazz)
+		), "Usage of Writer not detected.");
 	}
-
-	@Test
-	void sceneMethodRemoveTest() {
-		helper.classExist("lab.Scene");
-		Class<?> c = helper.getClass("lab.Scene");
-		helper.hasMethod(c, "remove", void.class, helper.getClass("DrawableSimulable"));
-		;
-	}
-
-	@Test
-	void lochnessMethodAddTest() {
-		helper.classExist("LochNess");
-		Class<?> c = helper.getClass("LochNess");
-		helper.hasMethod(c, "addDeadListener");
-	}
-
 	@Test
-	void lochnessMethodRemoveTest() {
-		helper.classExist("LochNess");
-		Class<?> c = helper.getClass("LochNess");
-		helper.hasMethod(c, "removeDeadListener");
+	void detectUsageOfExceptionClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().filter(name -> !name.startsWith("javafx.")).map(className -> {
+			try {
+				return Class.forName(className);
+			} catch (Throwable e) {
+				System.out.println(e.getMessage());
+			}
+			return Object.class;
+		}).anyMatch(clazz -> 
+		Exception.class.isAssignableFrom(clazz)
+		), "Usage of Exception not detected.");
 	}
-
-	@Test
-	void lochnessMethodFireTest() {
-		helper.classExist("LochNess");
-		Class<?> c = helper.getClass("LochNess");
-		assertTrue(helper.countMethodRegexp(c, "fire.*") > 0, "Method fire.* in LochNess not found.");
-	}
-
-	@Test
-	void zIndexMethodTest() {
-		helper.classExist("DrawableSimulable");
-		Class<?> c = helper.getClass("DrawableSimulable");
-		helper.hasMethodRegexp(c, "get[zZ][iI]ndex", int.class, new Class[0]);
-	}
-
 	@Test
-	void zIndexFieldTest() {
-		helper.classExist("WorldEntity");
-		Class<?> c = helper.getClass("WorldEntity");
-		helper.hasProperty(c, "[zZ][iI]ndex", int.class, false);
+	void detectUsageOfIOExceptionClassTest() {
+		assertTrue(helper.getNameOfAllClasses().stream().map(className -> {
+			try {
+				return Class.forName(className);
+			} catch (ClassNotFoundException e) {
+				System.out.println(e.getMessage());
+			}
+			return Object.class;
+		}).anyMatch(clazz -> IOException.class.isAssignableFrom(clazz)), "Usage of IOException not detected.");
 	}
 }
diff --git a/src/test/java/jez04/structure/test/StructureHelper.java b/src/test/java/jez04/structure/test/StructureHelper.java
index aef0cd0..7e10c45 100644
--- a/src/test/java/jez04/structure/test/StructureHelper.java
+++ b/src/test/java/jez04/structure/test/StructureHelper.java
@@ -9,6 +9,7 @@ import java.io.PrintStream;
 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;
@@ -19,9 +20,10 @@ import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import org.junit.jupiter.api.Assertions;
@@ -42,6 +44,22 @@ class StructureHelper {
 		assertTrue(allClasses.stream().anyMatch(c -> c.endsWith(name)), "Class/Interface " + name + " not found");
 	}
 
+	public Class<?> getClassDirectly(String name) {
+		try {
+			return Class.forName(name);
+		} 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 Class<?> getClass(String name) {
 		String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null);
 		if (className == null) {
@@ -111,6 +129,7 @@ class StructureHelper {
 		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();
 	}
@@ -155,16 +174,21 @@ class StructureHelper {
 				"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) {
 		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) {
+		Set<String> allClassesName = new TreeSet<>();
+		dynamicaliFoundSomeClass(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;
@@ -172,7 +196,6 @@ class StructureHelper {
 				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.")
@@ -184,22 +207,29 @@ class StructureHelper {
 			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);
+			allClassesName.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> {
+				System.out.println(">>> " + c);
 				return true;
 			})));
 		}
-		for (String string : allClasses) {
+		for (String string : allClassesName) {
 			System.out.println(string);
 		}
-		return allClasses;
+		return allClassesName;
 	}
 
-	public void dynamicaliFoundSomeClass(List<String> initClassesName) {
+	private static final List<String> dirsToSkip = List.of("jez04", "META-INF");
+	private static final List<String> filesToSkip = List.of("module-info.class");
+
+	public void dynamicaliFoundSomeClass(Set<String> allClassesName) {
 		URL myClassUrl = StructureHelper.class.getResource("ClassStructureTest.class");
 		myClassUrl.getFile();
 		try {
-			Path classRoot = Paths.get(myClassUrl.toURI()).getParent().getParent().getParent().getParent();
+			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");
 			}
@@ -209,7 +239,7 @@ class StructureHelper {
 
 				@Override
 				public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
-					if (List.of("jez04", "META-INF").contains(dir.getFileName().toString())) {
+					if (dirsToSkip.contains(dir.getFileName().toString())) {
 						return FileVisitResult.SKIP_SUBTREE;
 					}
 					return FileVisitResult.CONTINUE;
@@ -217,18 +247,20 @@ class StructureHelper {
 
 				@Override
 				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-					System.out.println("VISIT: " + file);
-					if ("module-info.class".equals(file.getFileName().toString())) {
+					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, '.');
-					initClassesName.add(foundClassName);
-					return FileVisitResult.TERMINATE;
+					addClassAndAllRef(allClassesName, foundClassName);
+					return FileVisitResult.CONTINUE;
 				}
 
 				@Override
@@ -245,4 +277,32 @@ class StructureHelper {
 			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();
+		}
+	}
 }
-- 
GitLab