Skip to content
Snippets Groups Projects
Commit 580c35bf authored by jez04's avatar jez04
Browse files

feat: :tada: solution

parent 0b9ddfaa
No related merge requests found
...@@ -3,3 +3,5 @@ ...@@ -3,3 +3,5 @@
.project .project
.classpath .classpath
.idea/ .idea/
*.mv.db
*.trace.db
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
<maven.compiler.target>21</maven.compiler.target> <maven.compiler.target>21</maven.compiler.target>
</properties> </properties>
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
</dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-controls</artifactId>
......
package lab;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class DbConnector {
private static final String JDBC_CONECTIN_STRING = "jdbc:h2:file:./scoreDB";
public static List<Score> getAll() {
return queryScore("select * from scores;");
}
public static List<Score> getFirstTen() {
return queryScore("select * from scores order by points desc limit 10;");
}
private static List<Score> queryScore(String query) {
List<Score> result = new ArrayList<>();
try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING);
Statement stm = con.createStatement();
ResultSet rs = stm.executeQuery(query);) {
while (rs.next()) {
result.add(new Score(rs.getString("nick"), rs.getInt("points")));
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
public static void createTable() {
try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING);
Statement stm = con.createStatement();) {
stm.executeUpdate("CREATE TABLE if not exists scores (nick VARCHAR(50) NOT NULL, points INT NOT NULL);");
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void insertScore(Score score) {
try (Connection con = DriverManager.getConnection(JDBC_CONECTIN_STRING);
PreparedStatement stm = con.prepareStatement("INSERT INTO scores VALUES (?, ?)");) {
stm.setString(1, score.getName());
stm.setInt(2, score.getPoints());
stm.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package lab; package lab;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
......
package lab; package lab;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.RadioButton; import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup; import javafx.scene.control.ToggleGroup;
import javafx.scene.control.cell.PropertyValueFactory;
/** /**
* *
*/ */
public class MainScreenController { public class MainScreenController {
@FXML
private Button btnGenerateScore;
@FXML
private Button btnLoadAll;
@FXML
private Button btnLoadFirstTen;
@FXML
private TableView<Score> scores;
@FXML
private TableColumn<Score, String> nickColumn;
@FXML
private TableColumn<Score, Integer> pointsColumn;
@FXML @FXML
private ToggleGroup difficult; private ToggleGroup difficult;
...@@ -41,13 +63,46 @@ public class MainScreenController { ...@@ -41,13 +63,46 @@ public class MainScreenController {
this.app = app; this.app = app;
} }
@FXML @FXML
void btnGenerateScoreAction(ActionEvent event) {
Score score = Score.generate();
this.scores.getItems().add(score);
DbConnector.insertScore(score);
}
@FXML
void btnLoadAllAction(ActionEvent event) {
updateScoreTable(DbConnector.getAll());
}
@FXML
void btnLoadFirstTenAction(ActionEvent event) {
updateScoreTable(DbConnector.getFirstTen());
}
private void updateScoreTable(List<Score> scores) {
this.scores.getItems().clear();
this.scores.getItems().addAll(scores);
}
@FXML
void initialize() { void initialize() {
assert difficult != null : "fx:id=\"difficult\" was not injected: check your FXML file 'mainScreen.fxml'."; assert difficult != null : "fx:id=\"difficult\" was not injected: check your FXML file 'mainScreen.fxml'.";
assert name != null : "fx:id=\"name\" was not injected: check your FXML file 'mainScreen.fxml'."; assert name != null : "fx:id=\"name\" was not injected: check your FXML file 'mainScreen.fxml'.";
easy.getProperties().put(Difficult.class, Difficult.EASY); easy.getProperties().put(Difficult.class, Difficult.EASY);
medium.getProperties().put(Difficult.class, Difficult.MEDIUM); medium.getProperties().put(Difficult.class, Difficult.MEDIUM);
hard.getProperties().put(Difficult.class, Difficult.HARD); hard.getProperties().put(Difficult.class, Difficult.HARD);
nickColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
pointsColumn.setCellValueFactory(new PropertyValueFactory<>("points"));
initDB();
}
private void initDB() {
//Stream.generate(Score::generate).limit(10).toList();
DbConnector.createTable();
scores.getItems().addAll(DbConnector.getAll());
} }
} }
package lab;
import java.util.Random;
public class Score {
private static final Random RANDOM = new Random();
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 String toString() {
return "Score [name=" + name + ", points=" + points + "]";
}
public static Score generate() {
return new Score(getRandomNick(), RANDOM.nextInt(50, 300));
}
public static final String[] nicks = { "CyberSurfer", "PixelPioneer", "SocialSavvy", "DigitalDynamo", "ByteBuddy", "InstaGuru",
"TikTokTornado", "SnapMaster", "TweetTrendsetter", "ChatChampion", "HashtagHero", "EmojiEnthusiast",
"StoryStylist", "SelfieStar", "FilterFanatic", "VlogVirtuoso", "Memelord", "InfluencerInsider",
"StreamSupreme", "GeekyGizmo", "CodeCommander", "JavaJuggernaut", "ByteNinja", "SyntaxSamurai",
"ClassyCoder", "ObjectOmnipotent", "LoopLegend", "VariableVirtuoso", "DebugDemon", "CompilerCrusader",
"PixelProdigy", "VirtualVoyager", "AlgorithmAce", "DataDynamo", "ExceptionExpert", "BugBuster",
"SyntaxSorcerer", "CodeCrusader", "JavaJester", "NerdyNavigator", "CryptoCaptain", "SocialButterfly",
"AppArchitect", "WebWizard", "FunctionFreak", "PixelArtist", "CyberPhantom", "HackHero", "CacheChampion",
"ScreenSage", "WebWeaver", "LogicLover", "BitBlazer", "NetworkNomad", "ProtocolPioneer", "BinaryBoss",
"StackSultan", "SocialScribe", "RenderRuler", "ScriptSorcerer", "HTMLHero", "PixelProwler", "FrameFreak",
"DataDreamer", "BotBuilder", "ByteBishop", "KeyboardKnight", "DesignDaredevil", "JavaJuggler",
"SyntaxStrategist", "TechTactician", "ProgramProdigy", "BinaryBard", "PixelPoet", "GigabyteGuru",
"TechTrekker", "NetworkNinja", "DataDetective", "MatrixMaster", "CodeConductor", "AppAlchemist",
"ServerSage", "ClusterChampion", "ScriptSensei", "KeyboardKicker", "CacheCrafter", "SocialSpark",
"BinaryBeast", "CodeConnoisseur", "BitBrain", "VirtualVanguard", "SystemSculptor", "RenderRogue",
"CryptoConqueror", "MachineMonarch", "PixelPal", "CompilerCaptain", "BitBuilder", "TechTitan",
"CloudConqueror", "EchoExplorer", "FunctionFanatic", "RobotRanger" };
public static String getRandomNick() {
return nicks[RANDOM.nextInt(nicks.length)];
}
}
...@@ -2,6 +2,7 @@ module lab01 { ...@@ -2,6 +2,7 @@ module lab01 {
requires transitive javafx.controls; requires transitive javafx.controls;
requires javafx.fxml; requires javafx.fxml;
requires javafx.base; requires javafx.base;
requires java.sql;
opens lab to javafx.fxml; opens lab to javafx.fxml;
exports lab; exports lab;
} }
\ No newline at end of file
...@@ -4,13 +4,16 @@ ...@@ -4,13 +4,16 @@
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?> <?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?> <?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<BorderPane fx:id="menuPanel" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.MainScreenController"> <BorderPane fx:id="menuPanel" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="456.0" prefWidth="711.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.MainScreenController">
<top> <top>
<HBox prefWidth="200.0" BorderPane.alignment="CENTER"> <HBox prefWidth="200.0" BorderPane.alignment="CENTER">
<children> <children>
...@@ -49,4 +52,22 @@ ...@@ -49,4 +52,22 @@
</children> </children>
</HBox> </HBox>
</center> </center>
<right>
<VBox prefHeight="287.0" prefWidth="159.0" BorderPane.alignment="CENTER">
<children>
<TableView fx:id="scores" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
<columns>
<TableColumn fx:id="nickColumn" prefWidth="75.0" text="Nick" />
<TableColumn fx:id="pointsColumn" prefWidth="75.0" text="Points" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
<Button fx:id="btnGenerateScore" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnGenerateScoreAction" text="Generate new score" />
<Button fx:id="btnLoadAll" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnLoadAllAction" text="Load all from DB" />
<Button fx:id="btnLoadFirstTen" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnLoadFirstTenAction" text="Load first 10 from DB" />
</children>
</VBox>
</right>
</BorderPane> </BorderPane>
...@@ -2,144 +2,100 @@ package jez04.structure.test; ...@@ -2,144 +2,100 @@ 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.File;
import java.io.IOException; 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.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.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.reflections.Configuration;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
class ClassStructureTest { class ClassStructureTest {
StructureHelper helper = new StructureHelper(); StructureHelper helper = new StructureHelper();
@Test @Test
void gameControllerExistenceTest() { void mainScreenControllerExistenceTest() {
helper.classExist("GameController"); helper.classExist("MainScreenController");
} }
@Test @Test
void gameControllerFxmlTest() { void mainScreenControllerFxmlTest() {
helper.classExist("GameController"); helper.classExist("MainScreenController");
Class<?> c = helper.getClass("GameController"); Class<?> c = helper.getClass("MainScreenController");
helper.hasPropertyWithAnnotation(c, ".*", FXML.class); helper.hasPropertyWithAnnotation(c, ".*", FXML.class);
} }
@Test @Test
void gameControllerActionMethodTest() { void mainScreenControllerButtonActionMethodTest() {
helper.classExist("GameController"); helper.classExist("MainScreenController");
Class<?> c = helper.getClass("GameController"); Class<?> c = helper.getClass("MainScreenController");
helper.hasMethodRegexp(c, ".*", void.class, ActionEvent.class); long count = helper.countMethodRegexp(c, ".*", void.class, ActionEvent.class);
assertTrue(count > 1, "Only " + count+ " method handling button click found. Expected more then 1");
} }
@Test @Test
void gameControllerLambdasTest() { void mainScreenControllerTableViewTest() {
helper.classExist("GameController"); helper.classExist("MainScreenController");
Class<?> c = helper.getClass("GameController"); Class<?> c = helper.getClass("MainScreenController");
long lamdaCount = helper.countMethodRegexp(c, "lambda\\$.*"); helper.hasProperty(c, ".*", TableView.class, false);
long innerClasscount = helper.countClassesRegexp(".*GameController\\$.*");
assertTrue(lamdaCount + innerClasscount >= 3,
"At least 3 inner classes or lamdas required for GameController but only "
+ (lamdaCount + innerClasscount) + " found.");
} }
@Test
void deadListenerExistenceTest() {
helper.classExist("DeadListener");
}
@Test
void deadListenerEventMethodTest() {
helper.classExist("DeadListener");
Class<?> c = helper.getClass("DeadListener");
helper.hasMethod(c, "monsterDead");
}
@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.");
}
@Test @Test
void sceneMethodAddTest() { void mainScreenControllerTableColumnTest() {
helper.classExist("Level"); helper.classExist("MainScreenController");
Class<?> c = helper.getClass("Level"); Class<?> c = helper.getClass("MainScreenController");
helper.hasMethod(c, "add", void.class, helper.getClass("DrawableSimulable")); helper.hasProperty(c, ".*", TableColumn.class, false);
;
} }
@Test @Test
void levelMethodRemoveTest() { void dbConnectorTest() {
helper.classExist("Level"); helper.classExistRegexp(".*[Dd][Bb][cC]on.*");
Class<?> c = helper.getClass("Level");
helper.hasMethod(c, "remove", void.class, helper.getClass("DrawableSimulable"));
;
} }
@Test @Test
void monsterMethodAddTest() { void dbConnectorGetAllTest() {
helper.classExist("Monster"); helper.classExistRegexp(".*[Dd][Bb][cC]on.*");
Class<?> c = helper.getClass("Monster"); Class<?> scoreClass = helper.getClassRegexp(".*[sS]core.*");
helper.hasMethod(c, "addDeadListener"); Class<?> c = helper.getClassRegexp(".*[Dd][Bb][cC]on.*");
helper.hasMethodRegexp(c, ".*[aA]ll.*", List.class);
helper.hasMethodRegexp(c, ".*[iI]nsert.*", void.class, scoreClass);
} }
@Test @Test
void monsterMethodRemoveTest() { void dbConnectorInsertTest() {
helper.classExist("Monster"); helper.classExistRegexp(".*[Dd][Bb][cC]on.*");
Class<?> c = helper.getClass("Monster"); Class<?> scoreClass = helper.getClassRegexp(".*[sS]core.*");
Class<?> l = helper.getClass("DeadListener"); Class<?> c = helper.getClassRegexp(".*[Dd][Bb][cC]on.*");
helper.hasMethodRegexp(c, "remove.*", List.of(void.class, boolean.class), l); helper.hasMethodRegexp(c, ".*[iI]nsert.*", void.class, scoreClass);
} }
@Test @Test
void monsterMethodFireTest() { void dbConnectorContainsJdbcTest() throws URISyntaxException, IOException {
helper.classExist("Monster"); helper.classExistRegexp(".*[Dd][Bb][cC]on.*");
Class<?> c = helper.getClass("Monster"); Class<?> c = helper.getClassRegexp(".*[Dd][Bb][cC]on.*");
assertTrue(helper.countMethodRegexp(c, "fire.*") > 0, "Method fire.* in LochNess not found."); String src = helper.getSourceCode(c);
assertTrue(src.contains("jdbc:"), "No usage of jdbc detect.");
} }
@Test @Test
void zIndexMethodTest() { void dbConnectorContainsDriverManagerTest() throws URISyntaxException, IOException {
helper.classExist("DrawableSimulable"); helper.classExistRegexp(".*[Dd][Bb][cC]on.*");
Class<?> c = helper.getClass("DrawableSimulable"); Class<?> c = helper.getClassRegexp(".*[Dd][Bb][cC]on.*");
helper.hasMethodRegexp(c, "get[zZ][iI]ndex", int.class, new Class[0]); String src = helper.getSourceCode(c);
assertTrue(src.contains("DriverManager"), "No usage of DriverManager detect.");
} }
@Test @Test
void zIndexFieldTest() { void dbConnectorContainsSqlTest() throws URISyntaxException, IOException {
helper.classExist("WorldEntity"); helper.classExistRegexp(".*[Dd][Bb][cC]on.*");
Class<?> c = helper.getClass("WorldEntity"); Class<?> c = helper.getClassRegexp(".*[Dd][Bb][cC]on.*");
helper.hasProperty(c, "[zZ][iI]ndex", int.class, false); String src = helper.getSourceCode(c).toLowerCase();
assertTrue(src.contains("create "), "No usage of SQL create.");
assertTrue(src.contains("select "), "No usage of SQL select.");
assertTrue(src.contains("insert "), "No usage of SQL table.");
assertTrue(src.contains(" from "), "No usage of SQL from.");
assertTrue(src.contains(" table"), "No usage of SQL table.");
} }
} }
package jez04.structure.test; package jez04.structure.test;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; 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.lang.reflect.Parameter;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.file.FileVisitResult; import java.nio.file.FileVisitResult;
...@@ -19,10 +22,12 @@ import java.nio.file.Paths; ...@@ -19,10 +22,12 @@ import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes; 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.List; import java.util.List;
import java.util.Set; 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.Collectors;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
...@@ -43,11 +48,31 @@ class StructureHelper { ...@@ -43,11 +48,31 @@ class StructureHelper {
assertTrue(allClasses.stream().anyMatch(c -> c.endsWith(name)), "Class/Interface " + name + " not found"); assertTrue(allClasses.stream().anyMatch(c -> c.endsWith(name)), "Class/Interface " + name + " not found");
} }
public void classExistRegexp(String name) {
assertTrue(allClasses.stream().anyMatch(c -> c.matches(name)), "Class/Interface " + name + " not found");
}
public Class<?> getClassDirectly(String name) {
return loadClass(name, name);
}
public Class<?> getClassRegexp(String name) {
String className = allClasses.stream().filter(c -> c.matches(name)).findAny().orElse(null);
if (className == null) {
Assertions.fail("Class " + name + " not found.");
}
return loadClass(name, className);
}
public Class<?> getClass(String name) { public Class<?> getClass(String name) {
String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null); String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null);
if (className == null) { if (className == null) {
Assertions.fail("Class " + name + " not found."); Assertions.fail("Class " + name + " not found.");
} }
return loadClass(name, className);
}
private Class<?> loadClass(String name, String className) {
try { try {
return Class.forName(className); return Class.forName(className);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
...@@ -108,48 +133,87 @@ class StructureHelper { ...@@ -108,48 +133,87 @@ class StructureHelper {
+ Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", ")));
} }
public Method getMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, Class<?>... params) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
List<Method> foundMethods = methods.stream().filter(m -> m.getName().contains(methodName))
.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) { public long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
return methods.stream().filter(m -> m.getName().matches(methodNameRegexp)).count(); return methods.stream().filter(m -> m.getName().matches(methodNameRegexp)).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) { public long countClassesRegexp(String classNameRegexp) {
return getNameOfAllClasses().stream().filter(className -> className.matches(classNameRegexp)).count(); return getNameOfAllClasses().stream().filter(className -> className.matches(classNameRegexp)).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, public void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType,
Class<?>... params) { Class<?>... params) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)), assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)),
"No method " + methodNameRegexp); "No method " + methodNameRegexp);
assertTrue( assertTrue(
methods.stream().filter( methods.stream().filter(m -> m.getName().matches(methodNameRegexp))
m -> .filter(m -> m.getReturnType().equals(returnType))
m.getName().matches(methodNameRegexp)) .anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))),
.filter(
m ->
m.getReturnType().equals(returnType))
.anyMatch(m ->
Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))),
"Method " + methodNameRegexp + " has no all parrams:" "Method " + methodNameRegexp + " has no all parrams:"
+ Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", "))); + Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", ")));
} }
public void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Collection<Class<?>> returnTypeOnOf, public long countMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType,
Class<?>... params) { Class<?>... params) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods()); List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)), assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)),
"No method " + methodNameRegexp); "No method " + methodNameRegexp);
assertTrue( return methods.stream().filter(m -> m.getName().matches(methodNameRegexp))
methods.stream().filter( .filter(m -> m.getReturnType().equals(returnType))
m -> .filter(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))).count();
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, public void hasMethod(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName,
...@@ -179,16 +243,34 @@ class StructureHelper { ...@@ -179,16 +243,34 @@ class StructureHelper {
"Class " + clazz.getName() + " not extends class " + parentName); "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) { public void hasMethod(Class<?> interfaceDef, String methodName) {
List<Method> methods = Arrays.asList(interfaceDef.getMethods()); List<Method> methods = Arrays.asList(interfaceDef.getMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName); assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "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() { public Set<String> getNameOfAllClasses() {
List<String> initClassesName = new ArrayList<>(); Set<String> allClassesName = new TreeSet<>();
dynamicaliFoundSomeClass(initClassesName); dynamicalyFoundSomeClass(allClassesName);
initClassesName.addAll(List.of("lab.Routines", "lab.App", "lab.DrawingThread")); // allClassesName.addAll(List.of("cz.vsb.fei.lab.App", "lab.Routines", "lab.App", "lab.DrawingThread"));
for (String className : initClassesName) { for (String className : allClassesName) {
try { try {
Class.forName(className); Class.forName(className);
break; break;
...@@ -196,7 +278,6 @@ class StructureHelper { ...@@ -196,7 +278,6 @@ class StructureHelper {
System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage())); System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage()));
} }
} }
Set<String> allClasses = new HashSet<>();
for (Package p : Package.getPackages()) { for (Package p : Package.getPackages()) {
if (p.getName().startsWith("java.") || p.getName().startsWith("com.") || p.getName().startsWith("jdk.") if (p.getName().startsWith("java.") || p.getName().startsWith("com.") || p.getName().startsWith("jdk.")
|| p.getName().startsWith("javafx.") || p.getName().startsWith("org.") || p.getName().startsWith("javafx.") || p.getName().startsWith("org.")
...@@ -204,36 +285,39 @@ class StructureHelper { ...@@ -204,36 +285,39 @@ class StructureHelper {
|| p.getName().startsWith("javassist")) { || p.getName().startsWith("javassist")) {
continue; continue;
} }
System.out.println(p.getName()); // System.out.println(p.getName());
Configuration conf = new ConfigurationBuilder().addScanners(Scanners.SubTypes.filterResultsBy(pc -> true)) Configuration conf = new ConfigurationBuilder().addScanners(Scanners.SubTypes.filterResultsBy(pc -> true))
.forPackages(p.getName()); .forPackages(p.getName());
Reflections reflections = new Reflections(conf); Reflections reflections = new Reflections(conf);
allClasses.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> { allClassesName.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> {
System.out.println(c); // System.out.println(">>> " + c);
return true; return true;
}))); })));
} }
for (String string : allClasses) { return allClassesName;
System.out.println(string);
}
return allClasses;
} }
public void dynamicaliFoundSomeClass(List<String> initClassesName) { private static final List<String> dirsToSkip = List.of("jez04", "META-INF");
URL myClassUrl = StructureHelper.class.getResource("ClassStructureTest.class"); private static final List<String> filesToSkip = List.of("module-info.class");
myClassUrl.getFile();
public void dynamicalyFoundSomeClass(Set<String> allClassesName) {
URL myClassUrl = StructureHelper.class.getResource(this.getClass().getSimpleName() + ".class");
try { 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())) { if ("test-classes".equals(classRoot.getFileName().toString())) {
classRoot = classRoot.getParent().resolve("classes"); classRoot = classRoot.getParent().resolve("classes");
} }
System.out.println("class root: " + classRoot); // System.out.println("class root: " + classRoot);
final Path classRootFinal = classRoot; final Path classRootFinal = classRoot;
Files.walkFileTree(classRoot, new FileVisitor<Path>() { Files.walkFileTree(classRoot, new FileVisitor<Path>() {
@Override @Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 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.SKIP_SUBTREE;
} }
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
...@@ -241,18 +325,20 @@ class StructureHelper { ...@@ -241,18 +325,20 @@ class StructureHelper {
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("VISIT: " + file); if (filesToSkip.contains(file.getFileName().toString())) {
if ("module-info.class".equals(file.getFileName().toString())) {
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
} }
if (!file.getFileName().toString().endsWith(".class")) { if (!file.getFileName().toString().endsWith(".class")) {
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
} }
if (file.getFileName().toString().contains("$")) {
return FileVisitResult.CONTINUE;
}
String foundClassName = classRootFinal.relativize(file).toString(); String foundClassName = classRootFinal.relativize(file).toString();
foundClassName = foundClassName.substring(0, foundClassName.length() - 6) foundClassName = foundClassName.substring(0, foundClassName.length() - 6)
.replace(File.separatorChar, '.'); .replace(File.separatorChar, '.');
initClassesName.add(foundClassName); addClassAndAllRef(allClassesName, foundClassName);
return FileVisitResult.TERMINATE; return FileVisitResult.CONTINUE;
} }
@Override @Override
...@@ -269,4 +355,34 @@ class StructureHelper { ...@@ -269,4 +355,34 @@ class StructureHelper {
e.printStackTrace(); 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();
}
}
} }
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