]> uap-core.de Git - rssreader.git/commitdiff
add initial build system and some code
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 6 Jun 2025 16:54:33 +0000 (18:54 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 6 Jun 2025 16:54:33 +0000 (18:54 +0200)
14 files changed:
.gitignore [new file with mode: 0644]
pom.xml [new file with mode: 0644]
rss-application/.gitignore [new file with mode: 0644]
rss-application/pom.xml [new file with mode: 0644]
rss-application/src/main/kotlin/Main.kt [new file with mode: 0644]
ui-java/.gitignore [new file with mode: 0644]
ui-java/pom.xml [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/Application.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/Toolkit.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/UiObject.java [new file with mode: 0644]
ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java [new file with mode: 0644]
ui-java/src/test/java/de/unixwork/ui/demo/Main.java [new file with mode: 0644]
ui-kotlin/.gitignore [new file with mode: 0644]
ui-kotlin/pom.xml [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8f5d5fa
--- /dev/null
@@ -0,0 +1,7 @@
+.idea/
+*.iml
+*.iws
+out/
+.idea_modules/
+.DS_Store
+/target/
diff --git a/pom.xml b/pom.xml
new file mode 100644 (file)
index 0000000..c99dc62
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>de.unixwork</groupId>
+  <artifactId>rssreader</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <name>rssreader</name>
+  <url>http://unixwork.de/</url>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <maven.compiler.release>24</maven.compiler.release>
+  </properties>
+  
+  <modules>
+    <module>ui-java</module>
+       <module>ui-kotlin</module>
+       <module>rss-application</module>
+  </modules>
+
+  <dependencyManagement>
+    <dependencies> 
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+  </dependencies>
+
+  <build>
+    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
+      <plugins>
+        
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
diff --git a/rss-application/.gitignore b/rss-application/.gitignore
new file mode 100644 (file)
index 0000000..5ff6309
--- /dev/null
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/rss-application/pom.xml b/rss-application/pom.xml
new file mode 100644 (file)
index 0000000..2599412
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>de.unixwork</groupId>
+    <artifactId>rss-application</artifactId>
+    <version>1.0-SNAPSHOT</version>
+       
+       <parent>
+        <artifactId>rssreader</artifactId>
+        <groupId>de.unixwork</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <kotlin.code.style>official</kotlin.code.style>
+        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>mavenCentral</id>
+            <url>https://repo1.maven.org/maven2/</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <sourceDirectory>src/main/kotlin</sourceDirectory>
+        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
+        <plugins>
+            <plugin>
+                <groupId>org.jetbrains.kotlin</groupId>
+                <artifactId>kotlin-maven-plugin</artifactId>
+                <version>2.1.20</version>
+                <executions>
+                    <execution>
+                        <id>compile</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>test-compile</id>
+                        <phase>test-compile</phase>
+                        <goals>
+                            <goal>test-compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.22.2</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>2.22.2</version>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>1.6.0</version>
+                <configuration>
+                    <mainClass>MainKt</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-test-junit5</artifactId>
+            <version>2.1.20</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>5.10.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-stdlib</artifactId>
+            <version>2.1.20</version>
+        </dependency>
+               
+               <dependency>
+            <groupId>de.unixwork</groupId>
+            <artifactId>ui-kotlin</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/rss-application/src/main/kotlin/Main.kt b/rss-application/src/main/kotlin/Main.kt
new file mode 100644 (file)
index 0000000..732b21a
--- /dev/null
@@ -0,0 +1,16 @@
+package de.unixwork
+
+//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
+// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
+fun main() {
+    val name = "Kotlin"
+    //TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
+    // to see how IntelliJ IDEA suggests fixing it.
+    println("Hello, " + name + "!")
+
+    for (i in 1..5) {
+        //TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
+        // for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
+        println("i = $i")
+    }
+}
\ No newline at end of file
diff --git a/ui-java/.gitignore b/ui-java/.gitignore
new file mode 100644 (file)
index 0000000..5ff6309
--- /dev/null
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/ui-java/pom.xml b/ui-java/pom.xml
new file mode 100644 (file)
index 0000000..0ac706d
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>de.unixwork</groupId>
+    <artifactId>ui-java</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>24</source>
+                    <target>24</target>
+                    <compilerArgs>
+                        <arg>--enable-preview</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>3.1.0</version> <!-- Or newer -->
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <mainClass>de.unixwork.ui.demo.Main</mainClass>
+                    <classpathScope>test</classpathScope>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <parent>
+        <artifactId>rssreader</artifactId>
+        <groupId>de.unixwork</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <properties>
+        <maven.compiler.source>24</maven.compiler.source>
+        <maven.compiler.target>24</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+</project>
diff --git a/ui-java/src/main/java/de/unixwork/ui/Application.java b/ui-java/src/main/java/de/unixwork/ui/Application.java
new file mode 100644 (file)
index 0000000..f2e31f3
--- /dev/null
@@ -0,0 +1,10 @@
+package de.unixwork.ui;
+
+public interface Application {
+
+    void startup();
+
+    default void shutdown() {
+
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/Toolkit.java b/ui-java/src/main/java/de/unixwork/ui/Toolkit.java
new file mode 100644 (file)
index 0000000..38925da
--- /dev/null
@@ -0,0 +1,159 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.*;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class Toolkit {
+    private static Toolkit instance;
+
+    private Application app;
+
+    // used for all strings and other memory, that is expected to be const
+    // and the UI toolkit does not create copies
+    private final Arena staticArena = Arena.ofShared();
+
+    private Linker linker;
+
+    private SymbolLookup lib;
+    private MethodHandle mainFunc;
+
+    private Toolkit(String appName) {
+        // load shared library
+        System.loadLibrary("uitk");
+        linker = Linker.nativeLinker();
+        lib = SymbolLookup.loaderLookup();
+
+        // get init function
+        MemorySegment ui_init_addr = lib.find("ui_init").orElseThrow();
+        FunctionDescriptor ui_init_sig = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
+        MethodHandle ui_init = linker.downcallHandle(ui_init_addr, ui_init_sig);
+
+        // create static/const C string
+        MemorySegment appNameCStr = staticArena.allocateFrom(appName);
+        try {
+            ui_init.invoke(appNameCStr, 0, MemorySegment.NULL);
+        } catch (Throwable e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        initFunctions();
+
+        UiObjectFuncs.init(linker, lib);
+    }
+
+    private void initFunctions() {
+        FunctionDescriptor sigv_v = FunctionDescriptor.ofVoid(); // void func(void)
+
+        MemorySegment ui_main_addr = lib.find("ui_main").orElseThrow();
+        mainFunc = linker.downcallHandle(ui_main_addr, sigv_v);
+    }
+
+    private static Toolkit getInstance() {
+        if(Toolkit.instance == null) {
+            Toolkit.init("app1");
+        }
+        return Toolkit.instance;
+    }
+    
+    public static void init(String appName) {
+        if(Toolkit.instance != null) {
+            return;
+        }
+        Toolkit.instance = new Toolkit(appName);
+    }
+
+    private static void onStartup(MemorySegment unused1, MemorySegment unused2) {
+        Toolkit toolkit = Toolkit.getInstance();
+        if(toolkit.app != null) {
+            toolkit.app.startup();
+        }
+    }
+
+    private static void onShutdown(MemorySegment unused1, MemorySegment unused2) {
+        Toolkit toolkit = Toolkit.getInstance();
+        if(toolkit.app != null) {
+            toolkit.app.shutdown();
+        }
+    }
+
+    private static void onOpen(MemorySegment unused1, MemorySegment unused2) {
+        Toolkit toolkit = Toolkit.getInstance();
+        if(toolkit.app != null) {
+            // TODO
+        }
+    }
+
+    public static void runApplication(Application app) {
+        Toolkit toolkit = Toolkit.getInstance();
+        toolkit.app = app;
+
+        // create method handles for native functions
+        FunctionDescriptor handlerSig = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS);
+        MethodHandle onstartup = toolkit.linker.downcallHandle(toolkit.lib.find("ui_onstartup").orElseThrow(), handlerSig);
+        MethodHandle onshutdown = toolkit.linker.downcallHandle(toolkit.lib.find("ui_onexit").orElseThrow(), handlerSig);
+        MethodHandle onopen = toolkit.linker.downcallHandle(toolkit.lib.find("ui_onopen").orElseThrow(), handlerSig);
+
+        // get java wrapper method handles
+        MethodHandle onstartupCallback = null;
+        MethodHandle onshutdownCallback = null;
+        MethodHandle onopenCallback = null;
+        try {
+            onstartupCallback = MethodHandles.lookup().findStatic(
+                    Toolkit.class,
+                    "onStartup",
+                    MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class));
+            onshutdownCallback = MethodHandles.lookup().findStatic(
+                    Toolkit.class,
+                    "onShutdown",
+                    MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class));
+            onopenCallback = MethodHandles.lookup().findStatic(
+                    Toolkit.class,
+                    "onOpen",
+                    MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class));
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        try (Arena arena = Arena.ofConfined()) {
+            // create native function pointers for java methods
+            FunctionDescriptor callbackDescriptor = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS);
+            MemorySegment onStartupFunc = toolkit.linker.upcallStub(
+                    onstartupCallback,
+                    callbackDescriptor,
+                    arena);
+            MemorySegment onShutdownFunc = toolkit.linker.upcallStub(
+                    onshutdownCallback,
+                    callbackDescriptor,
+                    arena);
+            MemorySegment onOpenFunc = toolkit.linker.upcallStub(
+                    onopenCallback,
+                    callbackDescriptor,
+                    arena);
+
+            // register java application callbacks
+            onstartup.invoke(onStartupFunc, MemorySegment.NULL);
+            onshutdown.invoke(onShutdownFunc, MemorySegment.NULL);
+            onopen.invoke(onOpenFunc, MemorySegment.NULL);
+
+            // run ui_main(), which invokes the application callback functions
+            Toolkit.mainloop();
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /*
+     * usually this should not be called directly, use runApplication instead
+     */
+    public static void mainloop() {
+        try {
+            Toolkit.getInstance().mainFunc.invoke();
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/UiObject.java b/ui-java/src/main/java/de/unixwork/ui/UiObject.java
new file mode 100644 (file)
index 0000000..374f76d
--- /dev/null
@@ -0,0 +1,19 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.MemorySegment;
+
+public class UiObject {
+    MemorySegment ptr;
+
+    UiObject(MemorySegment ptr) {
+        this.ptr = ptr;
+    }
+
+    public static UiObject createWindow(String title) {
+        return UiObjectFuncs.instance.window(title);
+    }
+
+    public void show() {
+        UiObjectFuncs.instance.show(this);
+    }
+}
diff --git a/ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java b/ui-java/src/main/java/de/unixwork/ui/UiObjectFuncs.java
new file mode 100644 (file)
index 0000000..4f2071e
--- /dev/null
@@ -0,0 +1,49 @@
+package de.unixwork.ui;
+
+import java.lang.foreign.*;
+import java.lang.invoke.MethodHandle;
+
+class UiObjectFuncs {
+    static UiObjectFuncs instance;
+
+    MethodHandle ui_show;
+    MethodHandle ui_window;
+
+    private UiObjectFuncs(Linker linker, SymbolLookup lib) {
+        // void* func(void*, void*)
+        FunctionDescriptor sigm_mm = FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
+        // void func(void*)
+        FunctionDescriptor sigv_m = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
+
+        MemorySegment ui_show_addr = lib.find("ui_show").orElseThrow();
+        MemorySegment ui_window_addr = lib.find("ui_window").orElseThrow();
+
+        ui_show = linker.downcallHandle(ui_show_addr, sigv_m);
+        ui_window = linker.downcallHandle(ui_window_addr, sigm_mm);
+    }
+
+    // must be called by the Toolkit constructor
+    static void init(Linker linker, SymbolLookup lib) {
+        UiObjectFuncs.instance = new UiObjectFuncs(linker, lib);
+    }
+
+    UiObject window(String title) {
+        MemorySegment obj = null;
+        try (Arena arena = Arena.ofConfined()) {
+            MemorySegment cstr = arena.allocateFrom(title);
+            obj = (MemorySegment) ui_window.invoke(cstr, MemorySegment.NULL);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+
+        return new UiObject(obj);
+    }
+
+    void show(UiObject obj) {
+        try {
+            ui_show.invoke(obj.ptr);
+        } catch (Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/ui-java/src/test/java/de/unixwork/ui/demo/Main.java b/ui-java/src/test/java/de/unixwork/ui/demo/Main.java
new file mode 100644 (file)
index 0000000..bda29de
--- /dev/null
@@ -0,0 +1,17 @@
+package de.unixwork.ui.demo;
+
+import de.unixwork.ui.*;
+
+public class Main implements Application{
+    public void startup() {
+        UiObject window = UiObject.createWindow("Test Window");
+        window.show();
+    }
+
+    public static void main(String[] args) {
+        System.out.println("UI Demo");
+        Toolkit.init("testapp");
+
+        Toolkit.runApplication(new Main());
+    }
+}
diff --git a/ui-kotlin/.gitignore b/ui-kotlin/.gitignore
new file mode 100644 (file)
index 0000000..5ff6309
--- /dev/null
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/ui-kotlin/pom.xml b/ui-kotlin/pom.xml
new file mode 100644 (file)
index 0000000..df08ad2
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>de.unixwork</groupId>
+    <artifactId>ui-kotlin</artifactId>
+    <version>1.0-SNAPSHOT</version>
+       
+       <parent>
+        <artifactId>rssreader</artifactId>
+        <groupId>de.unixwork</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <kotlin.code.style>official</kotlin.code.style>
+        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>mavenCentral</id>
+            <url>https://repo1.maven.org/maven2/</url>
+        </repository>
+    </repositories>
+
+    <build>
+        <sourceDirectory>src/main/kotlin</sourceDirectory>
+        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
+        <plugins>
+            <plugin>
+                <groupId>org.jetbrains.kotlin</groupId>
+                <artifactId>kotlin-maven-plugin</artifactId>
+                <version>2.1.20</version>
+                <executions>
+                    <execution>
+                        <id>compile</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>test-compile</id>
+                        <phase>test-compile</phase>
+                        <goals>
+                            <goal>test-compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.22.2</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>2.22.2</version>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-test-junit5</artifactId>
+            <version>2.1.20</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>5.10.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-stdlib</artifactId>
+            <version>2.1.20</version>
+        </dependency>
+               
+               <dependency>
+            <groupId>de.unixwork</groupId>
+            <artifactId>ui-java</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>