diff --git a/AppWish/AppWish/dependency-reduced-pom.xml b/AppWish/AppWish/dependency-reduced-pom.xml
new file mode 100644
index 0000000..deae5e0
--- /dev/null
+++ b/AppWish/AppWish/dependency-reduced-pom.xml
@@ -0,0 +1,124 @@
+
+
+ 4.0.0
+ pn.dev
+ code-generator-gui-ollama
+ CodeGenerator-GUI
+ 1.8.1
+ The GUI interface for the pn.dev.code-generator-ollama library is included in this package
+ 2024
+
+
+ Peter
+ Peter Westin
+ snow_900@outlook.com
+
+ Security Champion
+ Backend Engineer
+
+ Central European Time
+
+
+
+
+
+ maven-compiler-plugin
+ 3.13.0
+
+
+ 19
+
+
+
+ org.openjfx
+ javafx-maven-plugin
+ 0.0.8
+
+
+ default-cli
+
+ pn.app_wish.Main
+ app
+ app
+ app
+ true
+ true
+ true
+
+
+
+
+
+ maven-shade-plugin
+ 3.6.0
+
+
+ package
+
+ shade
+
+
+
+
+ pn.app_wish.Main
+
+
+
+
+
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.11.0-M2
+ test
+
+
+ opentest4j
+ org.opentest4j
+
+
+ junit-platform-commons
+ org.junit.platform
+
+
+ apiguardian-api
+ org.apiguardian
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.11.0-M2
+ test
+
+
+ junit-platform-engine
+ org.junit.platform
+
+
+ apiguardian-api
+ org.apiguardian
+
+
+
+
+
+
+ github
+ GitHub pwgit-create Apache Maven Packages
+ https://maven.pkg.github.com/pwgit-create/APPWISH_OLLAMA
+
+
+
+ https://sonarcloud.io
+ UTF-8
+ 19.0.2.1
+ 5.11.0-M2
+ pn-dev
+
+
diff --git a/AppWish/AppWish/pom.xml b/AppWish/AppWish/pom.xml
index abf7d34..6d8d0c8 100644
--- a/AppWish/AppWish/pom.xml
+++ b/AppWish/AppWish/pom.xml
@@ -5,7 +5,7 @@
4.0.0pn.devcode-generator-gui-ollama
- 1.8.1
+ 2.0CodeGenerator-GUI
@@ -45,7 +45,7 @@
pn.devcode-generator-ollama
- 1.8.1
+ 2.0org.openjfx
diff --git a/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java b/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java
index 746dfe4..4cf00ab 100644
--- a/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java
+++ b/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java
@@ -23,10 +23,11 @@
import org.slf4j.LoggerFactory;
import org.slf4j.simple.SimpleLogger;
+import pn.app_wish.model.AppCmd;
+import pn.app_wish.model.CodeBaseCmd;
import pn.app_wish.constant.CodeEvent;
import pn.app_wish.constant.GUIConstants;
import pn.app_wish.constant.StaticAppWishConstants;
-import pn.app_wish.util.AppWishUtil;
import pn.cg.app_system.AppSystem;
import pn.cg.app_system.code_generation.model.CompilationJob;
import pn.cg.datastorage.DataStorage;
@@ -38,12 +39,13 @@
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
-import static pn.app_wish.constant.GUIConstants.APP_HISTORY_STAGE_TILE;
-import static pn.app_wish.constant.GUIConstants.DEFAULT_FXML_FILE;
+import static pn.app_wish.constant.GUIConstants.*;
+import static pn.app_wish.constant.StaticAppWishConstants.*;
public class AppWish extends Application {
@@ -67,6 +69,8 @@ public class AppWish extends Application {
public Button btn_StopGeneratedApp;
@FXML
public ImageView logo;
+ @FXML
+ public Button btn_super_app_creation;
private String javaExecutablePath;
private Process executingJavaAppProcess;
@@ -100,11 +104,13 @@ public void start(Stage primaryStage) throws IOException {
System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "DEBUG");
Parent root = FXMLLoader.load(requireNonNull(getClass().getClassLoader().getResource(DEFAULT_FXML_FILE)));
mainStage = primaryStage;
+ mainStage.setResizable(false);
primaryStage.setTitle(GUIConstants.DEFAULT_STAGE_TITLE);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+
}
/**
@@ -149,7 +155,7 @@ private void onAppWish(CodeEvent codeEvent) {
waitForCompilationResult();
- handleCompilationResult();
+ handleCompilationResult(false);
});
@@ -161,10 +167,12 @@ private void onRunJavaApp(ActionEvent ae) {
btn_StopGeneratedApp.setVisible(true);
if (javaExecutablePath != null) {
- System.out.println("Executing java app on path -> " + javaExecutablePath);
+
+ if (!output_label.isVisible()) {
+ log.info("Executing java app on path -> {}", javaExecutablePath);
+ }
try {
- ProcessBuilder pb;
- pb = new ProcessBuilder(StaticAppWishConstants.BASH_PATH, StaticAppWishConstants.C_ARGUMENT, StaticAppWishConstants.JAVA_TEXT + javaExecutablePath);
+ ProcessBuilder pb = GetProcessBuilderForRunningGeneratedJavaApplications();
executingJavaAppProcess = pb.inheritIO().start();
} catch (IOException e) {
throw new RuntimeException(e);
@@ -172,10 +180,31 @@ private void onRunJavaApp(ActionEvent ae) {
}
}
+ private final ProcessBuilder GetProcessBuilderForRunningGeneratedJavaApplications() {
+ ProcessBuilder pb = null;
+
+ final String classPath = javaExecutablePath.replace(MAIN_DOT_JAVA, NOTHING_STRING);
+
+ if (output_label.isVisible()) {
+ // Super App Creation
+
+ // Security
+ if (classPath.concat(MAIN_DOT_JAVA).equals(javaExecutablePath)) {
+ log.info("Executing java app on path -> {}", javaExecutablePath.replace(MAIN_DOT_JAVA, NOTHING_STRING) + MAIN_TEXT);
+ pb = new ProcessBuilder(new CodeBaseCmd(classPath).GetCMDForRunningCodeBaseApplication());
+ }
+ } else {
+ // New App
+ // Continue an App
+ pb = new ProcessBuilder(new AppCmd(javaExecutablePath).GetCMDForRunningCodeBaseApplication());
+ }
+ return pb;
+ }
+
@FXML
private void onViewAppHistory(ActionEvent ae) throws IOException {
- if(!isCodeGenerationOnGoing) {
+ if (!isCodeGenerationOnGoing) {
AnchorPane pane = FXMLLoader.load(
requireNonNull(getClass().getClassLoader().getResource(GUIConstants.APP_HISTORY_FXML_FILE)));
Scene scene = new Scene(pane);
@@ -220,21 +249,22 @@ private void startGuiThread(CodeEvent codeEvent) {
/**
* The method for the event CREATE_APPLICATION
*/
- private void codeEventCreateApplication(){
- if(!btn_StopGeneratedApp.isVisible()){
- setButtonGroupVisibilityForCodeGenerationButtons(false);
- output_label.setText("Generating code...");
- }
+ private void codeEventCreateApplication() {
+ if (!btn_StopGeneratedApp.isVisible()) {
+ setButtonGroupVisibilityForCodeGenerationButtons(false);
+ output_label.setText(GUIConstants.GENERATING_CODE_DEFAULT_TEXT);
+ }
}
+
/**
* The method for the event CONTINUE_ON_EXISTING_APPLICATION
*/
- private void codeEventContinueAnApplication(){
- if(!btn_StopGeneratedApp.isVisible()) {
+ private void codeEventContinueAnApplication() {
+ if (!btn_StopGeneratedApp.isVisible()) {
setButtonGroupVisibilityForCodeGenerationButtons(false);
- output_label.setText("Generating code...\nContinue with existing application");
- }
+ output_label.setText(GUIConstants.CONTINUING_CODE_TEXT);
}
+ }
/**
* Create application button event
@@ -260,7 +290,6 @@ private void continueOnExistingApplication(ActionEvent ae) {
}
}
-
/**
* Starts the AI Code-Generation if the text input field is not null
*/
@@ -290,20 +319,27 @@ private void waitForCompilationResult() {
}
}
+
/**
* If a compilation result exist , check if the singleton in code-generator-ollama contains a path for an executable Java file
* If the above is true , activate the "run application" button and remove the "generating code..." text
*/
- private void handleCompilationResult() {
+ private void handleCompilationResult(boolean isSuperGeneration) {
if (DataStorage.getInstance().getCompilationJob().isResult()) {
javaExecutablePath = DataStorage.getInstance().getJavaExecutionPath();
// Draw success or error texts, and show run app button
Platform.runLater(() -> {
- if (DataStorage.getInstance().getJavaExecutionPath() != null) {
- output_label.setVisible(false);
+ if (DataStorage.getInstance().getJavaExecutionPath() != null || isSuperGeneration) {
+ if (!isSuperGeneration) {
+ output_label.setVisible(false);
+ btn_run_application.setVisible(true);
+ }
btn_run_application.setVisible(true);
setButtonGroupVisibilityForCodeGenerationButtons(true);
isCodeGenerationOnGoing = false;
+ if (isSuperGeneration) {
+ output_label.setText(SUCCESS_ON_SUPER_APP_CREATION_TEXT);
+ }
} else {
output_label.setText("Something went wrong :(");
}
@@ -318,6 +354,7 @@ private void handleCompilationResult() {
private void setButtonGroupVisibilityForCodeGenerationButtons(boolean isVisible) {
btn_create_application.setVisible(isVisible);
btn_continue_on_application.setVisible(isVisible);
+ btn_super_app_creation.setVisible(isVisible);
}
/**
@@ -354,4 +391,42 @@ private List readTextByLinesFromFile(File file) {
return null;
}
}
+
+ @FXML
+ public void OnSuperAppCreationButton(ActionEvent ae) {
+
+ isCodeGenerationOnGoing = true;
+ DataStorage.getInstance().setCompilationJob(new CompilationJob(GUIConstants.DEFAULT_STAGE_TITLE));
+ ThreadPoolMaster.getInstance().getExecutor().execute(() -> {
+ StartGuiThreadForSuperAppCreation();
+
+ AppSystem.StartSuperAppGeneration(tf_input.getText(), true, false, new LinkedList<>(), false, null);
+
+ waitUntilAllClassesOfTheSuperAppCreationHasBeenImplemented();
+ handleCompilationResult(true);
+ });
+ }
+
+ /**
+ * Starts a thread that handles GUI Updates
+ */
+ private void StartGuiThreadForSuperAppCreation() {
+
+ Platform.runLater(() -> {
+ setButtonGroupVisibilityForCodeGenerationButtons(false);
+ setButtonGroupVisibilityToFalseForStartAndStopApplicationsButtons();
+ output_label.setText(GENERATING_CODE_BASE_TEXT);
+ output_label.setVisible(true);
+ });
+ }
+
+ /**
+ * Wait until the singleton in code-generator-ollama has created the entire super app
+ */
+ private void waitUntilAllClassesOfTheSuperAppCreationHasBeenImplemented() {
+
+ while (!DataStorage.getInstance().isSuperAppCreated()) {
+ }
+ }
+
}
\ No newline at end of file
diff --git a/AppWish/AppWish/src/main/java/pn/app_wish/constant/GUIConstants.java b/AppWish/AppWish/src/main/java/pn/app_wish/constant/GUIConstants.java
index d6db59c..a8d34c3 100644
--- a/AppWish/AppWish/src/main/java/pn/app_wish/constant/GUIConstants.java
+++ b/AppWish/AppWish/src/main/java/pn/app_wish/constant/GUIConstants.java
@@ -7,5 +7,11 @@ public class GUIConstants {
public static final String APP_HISTORY_FXML_FILE="app_history.fxml";
public static final String APP_HISTORY_STAGE_TILE="My apps";
+ public static final String GENERATING_CODE_DEFAULT_TEXT="Generating code...";
+ public static final String CONTINUING_CODE_TEXT="Continuing with existing application...";
+ public static final String GENERATING_CODE_BASE_TEXT="Generating codebase...";
+ public static final String SUCCESS_ON_SUPER_APP_CREATION_TEXT="Success :)";
+
+
}
diff --git a/AppWish/AppWish/src/main/java/pn/app_wish/constant/StaticAppWishConstants.java b/AppWish/AppWish/src/main/java/pn/app_wish/constant/StaticAppWishConstants.java
index d81eeee..32f7d06 100644
--- a/AppWish/AppWish/src/main/java/pn/app_wish/constant/StaticAppWishConstants.java
+++ b/AppWish/AppWish/src/main/java/pn/app_wish/constant/StaticAppWishConstants.java
@@ -3,7 +3,12 @@
public record StaticAppWishConstants() {
public static final String BASH_PATH = "/bin/bash";
public static final String C_ARGUMENT = "-c";
- public final static String JAVA_TEXT = "java ";
+ public static final String JAVA_TEXT = "java ";
+
+
+ public static final String MAIN_TEXT="Main";
+ public static final String MAIN_DOT_JAVA="Main.java";
+ public static final String NOTHING_STRING="";
public final static String CONTINUE_ON_APPLICATION_FILTER_ON_JAVA_EXTENSION = "*.java";
public final static String CONTINUE_ON_APPLICATION_FILTER_ON_JAVA_EXTENSION_DESCRIPTION = "A extension filter with purpose to only show .java files";
diff --git a/AppWish/AppWish/src/main/java/pn/app_wish/model/AppCmd.java b/AppWish/AppWish/src/main/java/pn/app_wish/model/AppCmd.java
new file mode 100644
index 0000000..f8d95af
--- /dev/null
+++ b/AppWish/AppWish/src/main/java/pn/app_wish/model/AppCmd.java
@@ -0,0 +1,10 @@
+package pn.app_wish.model;
+import pn.app_wish.constant.StaticAppWishConstants;
+
+public record AppCmd(String javaExecutablePath) {
+
+ public final String[] GetCMDForRunningCodeBaseApplication() {
+
+ return new String[]{StaticAppWishConstants.BASH_PATH,StaticAppWishConstants.C_ARGUMENT, StaticAppWishConstants.JAVA_TEXT + javaExecutablePath};
+ }
+}
diff --git a/AppWish/AppWish/src/main/java/pn/app_wish/model/CodeBaseCmd.java b/AppWish/AppWish/src/main/java/pn/app_wish/model/CodeBaseCmd.java
new file mode 100644
index 0000000..a6d3e11
--- /dev/null
+++ b/AppWish/AppWish/src/main/java/pn/app_wish/model/CodeBaseCmd.java
@@ -0,0 +1,12 @@
+package pn.app_wish.model;
+
+public record CodeBaseCmd(String classPath) {
+
+ public final String[] GetCMDForRunningCodeBaseApplication() {
+ final String JAVA_PATH = "/usr/bin/java";
+ final String C_ARGUMENT_SUPER_APP="-cp";
+ final String CLASS_NAME="Main";
+
+ return new String[]{JAVA_PATH,C_ARGUMENT_SUPER_APP,classPath,CLASS_NAME};
+ }
+}
diff --git a/AppWish/AppWish/src/main/resources/ollama_model.props b/AppWish/AppWish/src/main/resources/ollama_model.props
index ab1a2a4..786a39c 100644
--- a/AppWish/AppWish/src/main/resources/ollama_model.props
+++ b/AppWish/AppWish/src/main/resources/ollama_model.props
@@ -1 +1 @@
-MODEL_NAME=llama3:latest
+MODEL_NAME=codestral:22b
\ No newline at end of file
diff --git a/AppWish/AppWish/src/main/resources/start.fxml b/AppWish/AppWish/src/main/resources/start.fxml
index 67a25dc..a979c82 100644
--- a/AppWish/AppWish/src/main/resources/start.fxml
+++ b/AppWish/AppWish/src/main/resources/start.fxml
@@ -1,81 +1,63 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 2dd33fa..e288a04 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Turn Your App Ideas into Reality!
+# AppWish 2.0
Introducing AppWish, a groundbreaking platform that empowers you to transform your app concepts into fully functional applications.
With App Wish, you can unleash your creativity without worrying about the complexities of coding.
@@ -6,13 +6,31 @@ With App Wish, you can unleash your creativity without worrying about the comple
-![Logo](https://github.com/pwgit-create/APPWISH_OLLAMA/blob/master/AppWish/AppWish/src/main/resources/shooting_star.png?raw=true)
-## AppWish Quick Start Guide(Release binary)
-Unzip the file from the latest release and follow the information provided in the [latest release notes](https://github.com/pwgit-create/APPWISH_OLLAMA/releases/tag/v1.8.1) 😃.
+## Functionality
+
+
+
+* ### Code Base Generation
+Since version 2.0 its possible to generate code bases from an appwish prompt.
+If you are a developer or work professionally with code, this option is suitable for you.
+* ### New App
+Write a prompt about what your app should do and click on New App
+
+* ### Continue an Application
+Write a prompt with your inteded changes and click on Continue
+## Quick Start Guide(Release binary)
+Follow the information provided in the [latest release notes](https://github.com/pwgit-create/APPWISH_OLLAMA/releases/tag/v2.0) 😃.
+
+1. Unzip the file from the latest release
+2. Run the install script before starting AppWish
+
+
+
+![Logo](https://github.com/pwgit-create/APPWISH_OLLAMA/blob/master/AppWish/AppWish/src/main/resources/shooting_star.png?raw=true)
## Apps made with AppWish Ollama
[Stenography app](https://github.com/pwgit-create/Steganography-App)
@@ -65,7 +83,7 @@ The apps generated by App Wish are now conveniently saved in a designated folder
## What is the process for altering the AI model for AppWish?
-You can change the AI Model [here](https://github.com/pwgit-create/APPWISH_OLLMA/blob/master/AppWish/AppWish/src/main/resources/ollama_model.props) !
(If you don't want to use the CodeStral:22b model for x64 Linux or the LLama3 model for arm)
+You can change the AI Model [here](https://github.com/pwgit-create/APPWISH_OLLMA/blob/master/AppWish/AppWish/src/main/resources/ollama_model.props) !
(If you don't want to use the CodeStral:22b model
#### System Requirements
diff --git a/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml b/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml
index 7569340..40abefb 100644
--- a/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml
+++ b/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml
@@ -3,7 +3,7 @@
4.0.0pn.devcode-generator-ollama
- 1.7.2
+ 1.8.1The Java Application-Generator (pn.dev.code-generator-ollama) creates applications by giving a string of your desired features for a Java application, like this: AppSystem.StartCodeGenerator(String appWish)2024
@@ -86,9 +86,17 @@
org.apache.maven.pluginsmaven-surefire-plugin
- 3.1.2
+ 3.3.0test
+
+ surefire-api
+ org.apache.maven.surefire
+
+
+ surefire-extensions-api
+ org.apache.maven.surefire
+ maven-surefire-commonorg.apache.maven.surefire
diff --git a/cg/CodeGenerator/CodeGenerator/pom.xml b/cg/CodeGenerator/CodeGenerator/pom.xml
index 2b960c8..eacce77 100644
--- a/cg/CodeGenerator/CodeGenerator/pom.xml
+++ b/cg/CodeGenerator/CodeGenerator/pom.xml
@@ -6,7 +6,7 @@
pn.devcode-generator-ollama
- 1.8.1
+ 2.0The Java Application-Generator (pn.dev.code-generator-ollama) creates applications by giving a string of your desired features for a Java application, like this: AppSystem.StartCodeGenerator(String appWish)
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java
index 48a481b..a52850f 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java
@@ -3,11 +3,22 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import pn.cg.app_system.code_generation.model.SuperApp;
+import pn.cg.datastorage.DataStorage;
import pn.cg.ollama_ai_remote.OllamaRemoteSystem;
+import pn.cg.util.CodeGeneratorUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+import java.nio.file.Path;
+import java.util.LinkedList;
import java.util.List;
+import java.util.NoSuchElementException;
-import static pn.cg.util.CodeGeneratorUtil.isThisACreateNewAppRequest;
+import static pn.cg.datastorage.constant.ScriptConstants.COMPILE_CLASS_STORAGE;
public class AppSystem {
@@ -15,6 +26,7 @@ public class AppSystem {
private static int retryCounter = 1;
+
/**
* Makes a request to ollama and retries with a recursive strategy upon failure
*
@@ -84,6 +96,161 @@ public static void StartCodeGenerator(String continueWithImprovementText, String
StartCodeGenerator(continueWithImprovementText, true, false, false, javaClassName, javaFileContentInLines);
}
+ /**
+ * Starts an app generation with the strategy to ask for each class that is needed and then compile each class in a new request until it compiles
+ *
+ * @param superAppWish The App Wish from the user
+ * @param isFirstRun Flag that shows if this is the first request attempt to ollama
+ * @param appWishCompileResult A flag that states if the current compilation is successfull or not
+ * @param classList The data holder for the current super app generation implementation status
+ * @param superAppCreationComplete A flag that shows if the entire super app creation is complete or not
+ */
+ public static void StartSuperAppGeneration(String superAppWish, boolean isFirstRun, boolean appWishCompileResult, List classList,
+ boolean superAppCreationComplete, OllamaRemoteSystem ollamaRemoteSystem) {
+
+ // Get Class names for the super app generation
+ if (isFirstRun) {
+ log.info("Started the Super AppSystem (Long-time code base generation)");
+ DataStorage.getInstance().setListOfPathsToTmpFiles(new LinkedList());
+ ollamaRemoteSystem = new OllamaRemoteSystem();
+
+ try {
+ // List Super app directories (if any) and increment the number by one for next super app
+ DataStorage.getInstance().setSuperAppDirectoryName(CodeGeneratorUtil.getIncrementedSuperAppDirectoryName());
+ Files.createDirectory(new File(COMPILE_CLASS_STORAGE + File.separator + DataStorage.getInstance().getSuperAppDirectoryName()).toPath());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ retryCounter = 1;
+ classList = ollamaRemoteSystem.GetClassListForSuperAppCreation(superAppWish);
+ superAppCreationComplete = false;
+
+ // Set pointer class in singleton into one of the classes in the class list
+ SuperApp selectedClassToCreate = CodeGeneratorUtil.getARandomUnimplementedClass();
+ DataStorage.getInstance().setCurrentSuperClass(selectedClassToCreate);
+
+ // Generate the first class in the super app class list
+ appWishCompileResult = ollamaRemoteSystem.CreateSuperApp(selectedClassToCreate, true);
+
+ if (appWishCompileResult) {
+ SuperApp currentWorkingClass =DataStorage.getInstance().getCurrentSuperClass();
+ DataStorage.getInstance().getListOfCurrentSuperAppClasses()
+ .stream()
+ .filter(e -> e.getClassName()
+ .equalsIgnoreCase(currentWorkingClass.getClassName()))
+ .findFirst()
+ .get()
+ .setImplemented(true);
+ }
+ StartSuperAppGeneration(superAppWish, false, appWishCompileResult, classList, false, ollamaRemoteSystem);
+ }
+
+
+ // Continue with next class (on success) if any unimplemented classes remain, else end the super app creation successfully :)
+ if (appWishCompileResult && !isFirstRun && !superAppCreationComplete) {
+
+ log.info("Class Generated\nContinue...");
+
+ try {
+ // Select the next class to create (from the super app list) or complete the super app creation if no unimplemented elements exist
+ SuperApp selectedClassToCreate = CodeGeneratorUtil.getARandomUnimplementedClass();
+ DataStorage.getInstance().setCurrentSuperClass(selectedClassToCreate);
+
+ // Generate the next class in the list of the super app
+ appWishCompileResult = ollamaRemoteSystem.CreateSuperApp(DataStorage.getInstance().getCurrentSuperClass(), false);
+
+ if (appWishCompileResult) {
+ // Set the successfully compiled class to status implemented
+ SuperApp currentWorkingClass =DataStorage.getInstance().getCurrentSuperClass();
+
+ DataStorage.getInstance().getListOfCurrentSuperAppClasses()
+ .stream()
+ .filter(e -> e.getClassName()
+ .equalsIgnoreCase(currentWorkingClass.getClassName()))
+ .findFirst()
+ .get()
+ .setImplemented(true);
+
+ }
+ StartSuperAppGeneration(superAppWish, false, appWishCompileResult, classList, DataStorage.getInstance().isSuperAppCreated(), ollamaRemoteSystem);
+ }
+
+
+ // Success on the entire super generation!
+ catch (NoSuchElementException noSuchElementException) {
+
+ log.info("No more classes to implement in super app creation");
+ superAppCreationComplete = true;
+ DataStorage.getInstance().setSuperAppCreated(superAppCreationComplete);
+
+ // Write documentation file to the directory of the super app
+ CodeGeneratorUtil.WriteDocFileToSuperApp(DataStorage.getInstance().getListOfCurrentSuperAppClasses(),
+ new File(CodeGeneratorUtil.GetDocFilePathForSuperApp()));
+
+ // Delete tmp files that where added to the class path when compiling
+ List pathOfTmpFilesInSuperAppCreation = DataStorage.getInstance().getListOfPathsToTmpFiles();
+
+ pathOfTmpFilesInSuperAppCreation.forEach(p -> {
+ try {
+ Files.delete(p);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ });
+ }
+
+ }
+
+ // Retry compilation for a selected class
+ if (!appWishCompileResult && !DataStorage.getInstance().isSuperAppCreated()) {
+
+ log.info("Class did not compile, try again....");
+
+ appWishCompileResult = ollamaRemoteSystem.CreateSuperApp(DataStorage.getInstance().getCurrentSuperClass(), false);
+
+ if (appWishCompileResult) {
+ SuperApp currentWorkingClass =DataStorage.getInstance().getCurrentSuperClass();
+
+ DataStorage.getInstance().getListOfCurrentSuperAppClasses()
+ .stream()
+ .filter(e -> e.getClassName()
+ .equalsIgnoreCase(currentWorkingClass.getClassName()))
+ .findFirst()
+ .get()
+ .setImplemented(true);
+
+ try{
+ SuperApp selectedClassToCreate = CodeGeneratorUtil.getARandomUnimplementedClass();
+ DataStorage.getInstance().setCurrentSuperClass(selectedClassToCreate);}
+
+ // Success on the entire super generation!
+ catch (NoSuchElementException e){
+
+ log.info("No more classes to implement in super app creation");
+ superAppCreationComplete = true;
+ DataStorage.getInstance().setSuperAppCreated(superAppCreationComplete);
+
+ // Write documentation file to the directory of the super app
+ CodeGeneratorUtil.WriteDocFileToSuperApp(DataStorage.getInstance().getListOfCurrentSuperAppClasses(),
+ new File(CodeGeneratorUtil.GetDocFilePathForSuperApp()));
+
+ // Delete tmp files that where added to the class path when compiling
+ List pathOfTmpFilesInSuperAppCreation = DataStorage.getInstance().getListOfPathsToTmpFiles();
+ pathOfTmpFilesInSuperAppCreation.forEach(p -> {
+ try {
+ Files.delete(p);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ });
+ }
+ }
+ if(!DataStorage.getInstance().isSuperAppCreated()){
+ StartSuperAppGeneration(superAppWish, false, appWishCompileResult, classList, DataStorage.getInstance().isSuperAppCreated(), ollamaRemoteSystem);}
+ }
+ }
+
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/ClassCompiler.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/ClassCompiler.java
index 4748c7f..b3815e7 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/ClassCompiler.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/ClassCompiler.java
@@ -3,6 +3,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import pn.cg.datastorage.DataStorage;
import pn.cg.datastorage.ThreadPoolMaster;
import pn.cg.datastorage.constant.CommonStringConstants;
import pn.cg.datastorage.constant.ScriptConstants;
@@ -10,6 +11,7 @@
import pn.cg.util.TaskUtil;
+import java.nio.file.Path;
import java.util.concurrent.ExecutorService;
public class ClassCompiler {
@@ -21,21 +23,47 @@ public ClassCompiler() {
/**
* Tries to compile a file with java source code into byte code
- *
* @param className Class name of the class that we will try to compile
+ * @param superAppDir A String path that will be provided if it is a super app generation and left as null if not
*/
- public void compileClass(String className) {
+ private final void compile(String className, String superAppDir) {
+
+ boolean isSuperAppGeneration;
+
+ isSuperAppGeneration = superAppDir != null;
ExecutorService executor = ThreadPoolMaster.getInstance().getExecutor();
- log.debug("Compiler path -> {}", TaskUtil.addFilePathToClassName(className + CommonStringConstants.JAVA_FILE_EXTENSION));
+ if(isSuperAppGeneration)
+ log.info("Compiler path -> {}", TaskUtil.addFilePathOfSuperAppToClassName(className + CommonStringConstants.JAVA_FILE_EXTENSION, DataStorage.getInstance().getSuperAppDirectoryName()));
+ else
+ log.info("Compiler path -> {}", TaskUtil.addFilePathToClassName(className + CommonStringConstants.JAVA_FILE_EXTENSION));
String scriptToUse = ScriptConstants.JAVAC_SCRIPT_NAME;
log.debug("script used when compiling -> {}", scriptToUse);
+ if(isSuperAppGeneration)
+ executor.execute(new CompileClassTask(scriptToUse,new String[]{TaskUtil.addFilePathOfSuperAppToClassName(className + CommonStringConstants.JAVA_FILE_EXTENSION,DataStorage.getInstance().getSuperAppDirectoryName())}));
+ else
executor.execute(new CompileClassTask(scriptToUse, new String[]{TaskUtil.addFilePathToClassName(className + CommonStringConstants.JAVA_FILE_EXTENSION)}));
+ }
+ /**
+ * Tries to compile a file with java source code into byte code
+ * @param className Class name of the class that we will try to compile
+ */
+ public void compileClass(String className){
+ compile(className,null);
+ }
+
+ /**
+ *
+ * @param className Class name of the class that we will try to compile
+ * @param superAppDir The path to the directory of the super app
+ */
+ public void compileSuperClass(String className, String superAppDir){
+ compile(className,superAppDir);
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java
new file mode 100644
index 0000000..8ba6405
--- /dev/null
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java
@@ -0,0 +1,77 @@
+package pn.cg.app_system.code_generation.model;
+
+import pn.cg.util.StringUtil;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class serves as a data holder for the classes needed for an application and their implementation status
+ */
+public class SuperApp {
+ private final String className;
+ private boolean isImplemented;
+
+ /**
+ * If the class is implemented and contains methods they are stored here
+ */
+ private List methods;
+ private List constructors;
+
+
+ public SuperApp(String className, boolean isImplemented) {
+ this.className = className;
+ this.isImplemented = isImplemented;
+
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public boolean isImplemented() {
+ return isImplemented;
+ }
+
+ public void setImplemented(boolean implemented) {
+ isImplemented = implemented;
+ }
+
+ public List getMethods() {
+ return methods;
+ }
+
+ public void setMethods(List methods) {
+ this.methods = methods;
+ }
+
+ public List getConstructors() {
+ return constructors;
+ }
+
+ public void setConstructors(List constructors) {
+ this.constructors = constructors;
+ }
+
+ /**
+ * Gets a string with new lines that contains the methods if this instance is implemented and they exist
+ * @return String
+ */
+ public String toStringForMethods(){
+ StringBuilder sb = new StringBuilder();
+ methods.forEach(m -> sb.append(m).append("\n"));
+ return sb.toString().trim();
+ }
+ /**
+ * Gets a string with new lines that contains any constructors if this instance is implemented and they exist
+ * @return String
+ */
+ public String toStringForConstructors(){
+
+ StringBuilder sb = new StringBuilder();
+ constructors.forEach(c -> sb.append(c).append("\n"));
+ return sb.toString().trim();
+ }
+}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/enum_/OPTION_METHOD_CONSTRUCTOR.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/enum_/OPTION_METHOD_CONSTRUCTOR.java
new file mode 100644
index 0000000..eaeb9c7
--- /dev/null
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/enum_/OPTION_METHOD_CONSTRUCTOR.java
@@ -0,0 +1,3 @@
+package pn.cg.app_system.code_generation.model.enum_;
+
+public enum OPTION_METHOD_CONSTRUCTOR {METHOD,CONSTRUCTOR}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java
index edb936c..0901c08 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java
@@ -54,7 +54,7 @@ public String createCompileErrorQuestion(String compileErrorMessage) {
*/
public String createClassesNeededForAppWishQuestion() {
- return QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + appWish + QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_SUFFIX;
+ return QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + appWish + QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1;
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java
index 0face7c..c1e3022 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java
@@ -1,6 +1,10 @@
package pn.cg.datastorage;
import pn.cg.app_system.code_generation.model.CompilationJob;
+import pn.cg.app_system.code_generation.model.SuperApp;
+
+import java.nio.file.Path;
+import java.util.List;
public class DataStorage {
@@ -11,13 +15,48 @@ public class DataStorage {
*/
private volatile CompilationJob compilationJob;
+ /**
+ * Flag that tells if the entire super app creation is complete or not
+ */
+ private volatile boolean isSuperAppCreated;
+
+ /**
+ * List of super classes that are part of the super app creation
+ */
+ private List listOfCurrentSuperAppClasses;
+
+ /**
+ * The execution path for regular apps creation apps
+ */
private String javaExecutionPath;
+
+ /**
+ * Data holder for the current Super App Directory name
+ */
+ private String SuperAppDirectoryName;
+
+ /**
+ * The class that is selected for implementation tries in a super app creation process
+ */
+ private volatile SuperApp currentSuperClass;
+
+ /**
+ * This is the list of tmp files that is scheduled for deletion when the entire super app generation is complete
+ */
+ private List listOfPathsToTmpFiles;
+
private static DataStorage instance;
+ /**
+ * The path for the project root directory
+ */
+ private final Path PROJECT_ROOT_WORKING_DIR;
private DataStorage() {
this.compilationJob = getCompilationJob();
+ this.isSuperAppCreated = false;
+ this.PROJECT_ROOT_WORKING_DIR = Path.of(System.getProperty("user.dir"));
}
@@ -45,6 +84,55 @@ public String getJavaExecutionPath() {
public void setJavaExecutionPath(String javaExecutionPath) {
this.javaExecutionPath = javaExecutionPath;
}
+
+ public SuperApp getCurrentSuperClass() {
+ return currentSuperClass;
+ }
+
+ public void setCurrentSuperClass(SuperApp currentSuperClass) {
+ this.currentSuperClass = currentSuperClass;
+ }
+
+ public boolean isSuperAppCreated() {
+ return isSuperAppCreated;
+ }
+
+ public void setSuperAppCreated(boolean superAppCreated) {
+ isSuperAppCreated = superAppCreated;
+ }
+
+ public String getSuperAppDirectoryName() {
+ return SuperAppDirectoryName;
+ }
+
+ public void setSuperAppDirectoryName(String superAppDirectoryName) {
+ SuperAppDirectoryName = superAppDirectoryName;
+ }
+
+ public List getListOfCurrentSuperAppClasses() {
+ return listOfCurrentSuperAppClasses;
+ }
+
+ public void setListOfCurrentSuperAppClasses(List listOfCurrentSuperAppClasses) {
+ this.listOfCurrentSuperAppClasses = listOfCurrentSuperAppClasses;
+ }
+
+ public List getListOfPathsToTmpFiles() {
+ return listOfPathsToTmpFiles;
+ }
+
+ public void setListOfPathsToTmpFiles(List listOfPathsToTmpFiles) {
+ this.listOfPathsToTmpFiles = listOfPathsToTmpFiles;
+ }
+
+ public void addPathToTmpFileList(Path path){
+
+ this.listOfPathsToTmpFiles.add(path);
+ }
+
+ public Path getPROJECT_ROOT_WORKING_DIR() {
+ return PROJECT_ROOT_WORKING_DIR;
+ }
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/CommonStringConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/CommonStringConstants.java
index 54d8313..f2658a1 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/CommonStringConstants.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/CommonStringConstants.java
@@ -3,7 +3,7 @@
/**
* Holder of common message Strings
*/
-public class CommonStringConstants {
+public record CommonStringConstants() {
/**
* String that should be returned if a String value will be used for error logic
@@ -15,6 +15,11 @@ public class CommonStringConstants {
*/
public static final String JAVA_FILE_EXTENSION = ".java";
+ /**
+ * Class file extension
+ */
+ public static final String CLASS_FILE_EXTENSION=".class";
+
/**
* The start delimiter String that will be requested in the query to the LLM Model
*/
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/PathConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/PathConstants.java
index 8422f07..ddfd6e8 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/PathConstants.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/PathConstants.java
@@ -2,7 +2,7 @@
import java.io.File;
-public class PathConstants {
+public record PathConstants() {
public static final String RESOURCE_PATH = "src"+File.separator+"main"+File.separator+"resources"+File.separator;
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java
index f8cc747..f8a2c45 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java
@@ -1,5 +1,7 @@
package pn.cg.datastorage.constant;
+import javax.print.DocFlavor;
+
public record QuestionConstants() {
/**
@@ -32,23 +34,6 @@ public record QuestionConstants() {
public final static String CLASS_DID_NOT_COMPILE_PREFIX_2 = "The java code you’ve sent me did not compile ";
- /**
- * Prefix that should be sent to fetch a list of classes from the ollama model
- *
- * @use-info The app wish should be concatenated at the tail of this String
- * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
- * @chain-order 1/2
- */
- public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX = "Which classes are needed for java code on ";
-
- /**
- * Suffix for WHICH_CLASS_ARE_NEEDED_FOR_APP
- *
- * @use-info This String should be concatenated at the tail of the appWish (Instance variable in QuestionBuilder)
- * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
- * @chain-order 2/2
- */
- public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_SUFFIX = "=? please provide me the java classes in a numbered list ";
/**
* Optional Suffix to APP_WISH
@@ -137,4 +122,131 @@ public record QuestionConstants() {
public final static String ONLY_CODE ="Your answer should only contain code, any further explanations should be kept as comments within the code";
/// ***** ///
+
+ /*
+ * Super app - specific questions
+ */
+ /// ***** ///
+
+ /**
+ * Prefix that should be sent to fetch a list of classes from the ollama model
+ *
+ * @use-info The (super) appWish should be concatenated at the tail of this String
+ * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
+ * @chain-order 1/5
+ * @SuperApp-Question
+ */
+ public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX = "Which classes do we need to implement ourself in java to make an application with the features that is provided in the next coming lines?";
+
+ /**
+ * @use-info This is the string that will tell the AI-Model that the line above is the last line of the (super) appWish
+ * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
+ * @chain-order 2/5
+ * @SuperApp-Question
+ */
+ public final static String LAST_LINE_OF_SUPER_APP="The line above was the last line that included features of the app I need";
+
+ /**
+ *
+ * @use-info Text that specifies the format of the response from the AI-model
+ * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
+ * @chain-order 3/5
+ */
+ public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1 = "Please provide the name of the first java class and then make a new line for the second java class and then continue until you have listed all the class names of the application I need";
+
+
+ /**
+ * @use-info Additional guidelines regarding format in the response from the AI-model
+ * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
+ * @chain-order 4/5
+ */
+ public final static String ONLY_CLASS_NAMES_IN_ANSWER="Your response should only contain the needed classes name for the application and there shall be one class name per line, your reply must not contain anything else";
+
+ /**
+ * @use-info Clarify that no numbers or dots should be included in the response from the AI-model
+ * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX
+ * @chain-order 5/5
+ */
+ public final static String CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE="Your response should must not contain number,dots or spaces to state the order of the classes, there should only be one class name per line and nothing else";
+
+ /**
+ * This is the line that initiates the phase that happens after the classes for the super app has been stated
+ * @use-info Use this when the classes for the super app has been decided as the first line to the AI-model
+ */
+ public final static String FIRST_LINE_AFTER_CLASSES_HAS_BEEN_STATED_BY_MODEL="You have previously stated several classes that is needed to make my application";
+
+ /**
+ * Provide java code for a class
+ * @use-info Append the appWish at the tail of this question
+ */
+ public final static String PROVIDE_ME_JAVA_CODE_SUPER_APP_SPECIFIC=APP_WISH_PREFIX_FEATURE+"the class with name ";
+
+ /***
+ * Clarify the rules for the super app java class generation to the AI-model
+ */
+ public final static String CLARIFY_JAVA_CODE_IN_SUPER_APP_RULES="Make sure that the generated code for the java class is compatible with the other classes that you stated was needed for the application , that includes correct variable names and correct imports and class names";
+
+ /**
+ * Share information to the AI-Model that it always should include a Main class that contains the Main Method
+ */
+ public final static String MAIN_CLASS_SHOULD_ALWAYS_BE_ADDED_TO_THE_CLASS_LIST="The last entry in the class list that you will provide , please add a class called Main";
+
+ /**
+ * Instruct the AI-Model that the Main class is used to start the application (To avoid an extra class in the code base)
+ */
+ public final static String EXPLAIN_PURPOSE_WITH_MAIN_CLASS="The purpose with Main is to start the application but do not add that information in your response";
+
+ /**
+ * Share information to the AI-Model about the requirements for the implementation of the Main class ( In a super app generation process)
+ */
+ public final static String IMPLEMENT_MAIN_CLASS_IN_SUPER_APP_CREATION=WITH_MAIN_METHOD +" and that the body of that main method is empty or invokes a method in one of the other classes that we generated before";
+
+ /**
+ * Instruct the AI-Model to not include a main method unless the class name is main
+ */
+ public final static String NO_MAIN_CLASS_UNLESS_THE_CLASS_NAME_IS_MAIN="Do not include a main method unless the class name is Main or main";
+
+ /**
+ * Remind the AI-Model that the current class generation should consider the other classes (of the entire super app)
+ */
+ public final static String MAKE_SURE_IT_ALIGNS_WITH_OTHER_CLASSES="Please make sure that the class you are generating now will work with the following classes that we generated previously and implemented and if you forgot their names they will be provided for you in the next lines along with the methods that it contains";
+
+ /**
+ * Just a line stating that for the AI-Model that the line above was the last line of the list of classes and their method members
+ */
+ public final static String THAT_WAS_THE_LAST_LINE_OF_REMEMBER_CLASSES="The line above was the last line of class names to consider when creating the class";
+
+ /**
+ * A line that only should be included if it is the first class of N in a super app generation
+ * @chain-order 1/4
+ */
+ public final static String CONSIDER_ALL_CLASSES_IN_THIS_SUPER_APP_CREATION="Please note that the class that you will create is one of many in this application and you need to consider that when creating this class";
+
+ /**
+ * Clarify that the other classes are not implemented yet and can´t be referenced in the code yet
+ * @chain-order 2/4
+ */
+ public final static String CLASSES_THAT_ARE_INCLUDED_IN_THE_SUPER_APP="The classes that you need to consider are not yet implemented so you can not use references to those classes in your code for this class unless you provide them as comments, but you can still consider what methods those classes might need from this class";
+
+ /**
+ * Start line before unimplemented classes are listed
+ * @chain-order 3/4
+ */
+ public final static String THE_UNIMPLEMENTED_CLASSES_OF_THE_SUPER_APP="These unimplemented classes are provided for you in the next coming lines";
+
+ /**
+ * End line after all unimplemented classes has been listed
+ * @chain-order 4/4
+ */
+ public final static String LAST_LINE_OF_UNIMPLEMENTED_CLASSES_OF_THE_SUPER_APP="The line above was the last line that included unimplemented classes that will be included in this application in the future. Remember that you can not use references to those classes in your code for this class unless you provide them as comments";
+
+ /**
+ * Instruct the AI-Model to not assume that classes contains methods or constructor parameters that they do not
+ */
+ public final static String DO_NOT_ASSUME_THAT_CLASSES_CONTAINS_METHODS_OR_CONSTRUCTORS_THAT_THEY_DO_NOT="Please do not assume parameter types in methods or constructors of other classes and include them in the code if it is not stated in the query that they exists";
+
+ /// ***** ///
+
+
+
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/ScriptConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/ScriptConstants.java
index e34c2e9..53c9886 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/ScriptConstants.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/ScriptConstants.java
@@ -1,6 +1,6 @@
package pn.cg.datastorage.constant;
-public class ScriptConstants {
+public record ScriptConstants() {
/**
* Compile script for Linux
@@ -8,6 +8,9 @@ public class ScriptConstants {
public static final String JAVAC_SCRIPT_NAME = "compile_class.sh";
+ /**
+ * Folder for generated java applications
+ */
public static final String COMPILE_CLASS_STORAGE = PathConstants.RESOURCE_PATH+"java_source_code_classes_tmp";
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java
index a4dd590..628e5d7 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java
@@ -4,9 +4,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pn.cg.app_system.code_generation.ClassCompiler;
+import pn.cg.app_system.code_generation.model.SuperApp;
import pn.cg.app_wish.QuestionBuilder;
import pn.cg.datastorage.DataStorage;
+import pn.cg.datastorage.constant.CommonStringConstants;
+import pn.cg.datastorage.constant.PathConstants;
import pn.cg.datastorage.constant.QuestionConstants;
+import pn.cg.datastorage.constant.ScriptConstants;
import pn.cg.ollama_ai_remote.request.*;
import pn.cg.util.CodeGeneratorUtil;
import pn.cg.util.FileUtil;
@@ -15,10 +19,14 @@
import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.LinkedList;
import java.util.List;
-import static pn.cg.datastorage.constant.CommonStringConstants.ERROR;
-import static pn.cg.datastorage.constant.CommonStringConstants.JAVA_FILE_EXTENSION;
+import static pn.cg.datastorage.constant.CommonStringConstants.*;
+
/**
* This class holds the logic for the requests and responses to the OLLAMA AI API
@@ -27,6 +35,7 @@ public class OllamaRemoteSystem {
private final ClassCompiler classCompiler;
+
private final RequestHandler requestHandler;
private static final Logger log = LoggerFactory.getLogger(OllamaRemoteSystem.class);
@@ -50,7 +59,7 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i
boolean isRetryCompilation;
boolean tmpRetryCompilationValue;
- boolean isCreateNewApp = CodeGeneratorUtil.isThisACreateNewAppRequest(ifJavaAppShouldBeModifiedPath,contentOfJavaFileIfModifyRequest);
+ boolean isCreateNewApp = CodeGeneratorUtil.isThisACreateNewAppRequest(ifJavaAppShouldBeModifiedPath, contentOfJavaFileIfModifyRequest);
if (firstRun) {
isRetryCompilation = false;
@@ -65,26 +74,25 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i
log.error("Class did not compile\nSending new request... ");
}
if (DataStorage.getInstance().getCompilationJob() != null && !DataStorage.getInstance().getCompilationJob().isResult()) {
- if(isCreateNewApp)
- outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(QuestionConstants.CLASS_DID_NOT_COMPILE_PREFIX_2 + questionBuilder.createFeatureQuestion());
- else{
- outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(QuestionConstants.CLASS_DID_NOT_COMPILE_PREFIX_2 + appWish,ifJavaAppShouldBeModifiedPath,contentOfJavaFileIfModifyRequest);
- }
+ if (isCreateNewApp)
+ outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(QuestionConstants.CLASS_DID_NOT_COMPILE_PREFIX_2 + questionBuilder.createFeatureQuestion());
+ else {
+ outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(QuestionConstants.CLASS_DID_NOT_COMPILE_PREFIX_2 + appWish, ifJavaAppShouldBeModifiedPath, contentOfJavaFileIfModifyRequest);
+ }
}
}
if (firstRun) {
- if(isCreateNewApp)
- outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(questionBuilder.createFeatureQuestion());
- else
- outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(appWish,ifJavaAppShouldBeModifiedPath,
+ if (isCreateNewApp)
+ outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(questionBuilder.createFeatureQuestion());
+ else outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(appWish, ifJavaAppShouldBeModifiedPath,
contentOfJavaFileIfModifyRequest);
}
// Extract class name
String className = StringUtil.extractClassNameFromTextWithJavaClasses(outputFromOLLMA);
- log.debug("className -> " + className);
+ log.debug("className -> {}", className);
if (className.equalsIgnoreCase(ERROR)) {
//log.debug("Empty class name");
} else {
@@ -126,7 +134,126 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i
return DataStorage.getInstance().getCompilationJob().isResult();
}
+ /**
+ * Get a list of classes needed for the creation of the super app and sets the output list as reference in the shared singleton
+ *
+ * @param superAppWish The requirements for the super app in text format
+ * @return List
+ */
+ public synchronized List GetClassListForSuperAppCreation(String superAppWish) {
+ List superAppList = requestHandler.sendClassesNeededForSuperAppQuestionToOllamaInstance(superAppWish);
+ DataStorage.getInstance().setListOfCurrentSuperAppClasses(superAppList);
+ return superAppList;
+ }
+
+ public synchronized boolean CreateSuperApp(SuperApp classInSuperAppDesign, boolean isFirstRun) {
+
+ String outputFromOLLMA = "";
+
+ if (!isFirstRun) {
+
+ if (DataStorage.getInstance().getCompilationJob() != null) {
+
+ if (!DataStorage.getInstance().getCompilationJob().isResult()) {
+ log.error("Class did not compile\nSending new request... ");
+ outputFromOLLMA = requestHandler.sendSuperAppQuestionToOllamaInstance(classInSuperAppDesign);
+ } else {
+ log.info("Previous class compiled successfully\nSending new request for the next class in the list... ");
+ outputFromOLLMA = requestHandler.sendSuperAppQuestionToOllamaInstance(classInSuperAppDesign);
+ }
+ }
+ }
+
+ if (isFirstRun) {
+ log.info("First run in super app creation\nNo compile result is yet to exist!");
+ outputFromOLLMA = requestHandler.sendSuperAppQuestionToOllamaInstance(classInSuperAppDesign);
+ }
+
+
+ // Extract class name
+ String className = StringUtil.extractClassNameFromTextWithJavaClasses(outputFromOLLMA);
+ log.debug("className -> {}", className);
+
+
+ String javaSourceCode = outputFromOLLMA;
+
+ javaSourceCode = StringUtil.RemoveExtraStartDelimitersInResponse(javaSourceCode);
+
+ javaSourceCode = StringUtil.RemoveExtraEndDelimitersInResponse(javaSourceCode);
+
+ javaSourceCode = StringUtil.IncludeEveryThingAfterStartChar(javaSourceCode);
+
+ javaSourceCode = StringUtil.RemoveEveryThingAfterEndChar(javaSourceCode);
+
+ javaSourceCode = checkAndFixUnclosedBraceBuckets(javaSourceCode);
+ javaSourceCode = StringUtil.RemoveCommonAdditionStringsFromAiModels(javaSourceCode);
+
+
+ log.info("Java source code after modification = {}", javaSourceCode);
+ // Create file instance with class name and file extension
+ File file = new File(TaskUtil.addFilePathOfSuperAppToClassName(className + CommonStringConstants.JAVA_FILE_EXTENSION, DataStorage.getInstance().getSuperAppDirectoryName()));
+ if(className.equals("Main")){
+ // Save the path to shared storage (if user wants to execute the java app after the build
+ DataStorage.getInstance().setJavaExecutionPath(file.getAbsolutePath());}
+
+ // Write the Java code provided from OLLAMA to file
+ try {
+ FileUtil.writeDataToFile(file, javaSourceCode);
+ } catch (IOException e) {
+ log.error(e.toString());
+ throw new RuntimeException(e);
+ }
+
+ DataStorage.getInstance().getCompilationJob().setResult(null);
+ classCompiler.compileSuperClass(className, DataStorage.getInstance().getSuperAppDirectoryName());
+
+
+ while (DataStorage.getInstance().getCompilationJob().isResult() == null) {
+ }
+
+ if (DataStorage.getInstance().getCompilationJob().isResult()) {
+
+ try {
+ Thread.sleep(900);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+
+ // Set methods and constructors for the implemented class SuperApp Class representation
+ try {
+ CodeGeneratorUtil.SetMethodAndConstructorListForImplementedClass(className, Path.of(TaskUtil.addFilePathOfSuperAppToClassName(className + CommonStringConstants.CLASS_FILE_EXTENSION, DataStorage.getInstance().getSuperAppDirectoryName())));
+ } catch (MalformedURLException | ClassNotFoundException e) {
+ log.error("Could not set Methods or/ and constructors");
+ classInSuperAppDesign.setConstructors(new LinkedList());
+ classInSuperAppDesign.setMethods(new LinkedList());
+ }
+
+ // Copy class file to the script directory for the javac script, so it will be included in the class path
+ try {
+ Path destinationPathForTempFile= Path.of(DataStorage.getInstance().getPROJECT_ROOT_WORKING_DIR().toString()+File.separator+className+CLASS_FILE_EXTENSION);
+ Files.deleteIfExists(destinationPathForTempFile);
+ DataStorage.getInstance().addPathToTmpFileList(destinationPathForTempFile);
+ Files.copy(Path.of(TaskUtil.addFilePathOfSuperAppToClassName(className + CommonStringConstants.CLASS_FILE_EXTENSION, DataStorage.getInstance().getSuperAppDirectoryName())),destinationPathForTempFile);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+
+ log.info("Successful compilation of class, continue with next class");
+ } else {
+ log.info("Class did not compile , try again!");
+ }
+
+ return DataStorage.getInstance().getCompilationJob().isResult();
+ }
+
+ /**
+ * Checks if the current brace buckets pairs are even and if they are not , Append brace buckets until they are
+ *
+ * @param input java code
+ * @return String
+ */
private String checkAndFixUnclosedBraceBuckets(String input) {
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java
index 6505712..73b4646 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java
@@ -1,5 +1,7 @@
package pn.cg.ollama_ai_remote.request;
+import pn.cg.app_system.code_generation.model.SuperApp;
+
import java.util.List;
@@ -26,4 +28,19 @@ public interface RequestHandler {
*/
String sendQuestionToOllamaInstance(String question,String pathToJavaFileToModify,List contentOfExistingJavaFile);
+ /**
+ * Send a request to the AI-Model and ask which classes are needed for the super app creation
+ * @param question Question that contains text that describes requirements and functionality of a new super app
+ * @Recursive
+ * @return List that contains the class names for the super app (decided by the AI-model) and their implementation status
+ */
+ List sendClassesNeededForSuperAppQuestionToOllamaInstance(String question);
+
+ /**
+ * Send a request to the AI-Model where we ask it to implement the input super class with java code
+ * @param superAppClass A class in the super app project
+ * @return String with meta information on the current progress
+ */
+ String sendSuperAppQuestionToOllamaInstance(SuperApp superAppClass);
+
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java
index 12059a8..c24b736 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java
@@ -1,7 +1,9 @@
package pn.cg.ollama_ai_remote.request;
+import pn.cg.app_system.code_generation.model.SuperApp;
import pn.cg.datastorage.CodeGeneratorConfig;
+import pn.cg.datastorage.DataStorage;
import pn.cg.datastorage.constant.QuestionConstants;
import org.slf4j.Logger;
@@ -13,22 +15,41 @@
import io.github.amithkoujalgi.ollama4j.core.utils.Options;
import io.github.amithkoujalgi.ollama4j.core.utils.OptionsBuilder;
import io.github.amithkoujalgi.ollama4j.core.utils.PromptBuilder;
+import pn.cg.util.CodeGeneratorUtil;
+import pn.cg.util.StringUtil;
import java.io.IOException;
+import java.util.LinkedList;
import java.util.List;
-import static pn.cg.util.CodeGeneratorUtil.isThisACreateNewAppRequest;
+import static pn.cg.datastorage.constant.QuestionConstants.*;
+import static pn.cg.util.CodeGeneratorUtil.*;
+import static pn.cg.util.CodeGeneratorUtil.GetFormattedStringForAClassName;
public class RequestHandlerImpl implements RequestHandler {
- private final String HOST = "http://localhost:11434/";
+ private static final Logger log = LoggerFactory.getLogger(RequestHandlerImpl.class);
+ private final String HOST = "http://localhost:11434/";
+ private final OllamaAPI api;
+ private final Options options;
+ private final CodeGeneratorConfig codeGeneratorConfig;
- private static final Logger log = LoggerFactory.getLogger(RequestHandlerImpl.class);
public RequestHandlerImpl() {
+ this.api = new OllamaAPI(HOST);
+ this.codeGeneratorConfig = new CodeGeneratorConfig();
+ this.options = new OptionsBuilder()
+ .setNumCtx(codeGeneratorConfig.getNUM_CTX())
+ .setTopK(codeGeneratorConfig.getTOP_K())
+ .setNumPredict(codeGeneratorConfig.getNUM_PREDICT())
+ .setTemperature(codeGeneratorConfig.getTEMPERATURE())
+ .build();
+
+ api.setRequestTimeoutSeconds(100000);
+ log.info("Is OLLAMA server alive? -> {}", api.ping()); // This is your local OLLAMA server running on localhost and is used for the LLM model
}
@Override
@@ -40,24 +61,15 @@ public String sendQuestionToOllamaInstance(String question) {
@Override
public String sendQuestionToOllamaInstance(String question, String pathToJavaFileToModify, List contentOfExistingJavaFile) {
- OllamaAPI api = new OllamaAPI(HOST);
- boolean isThisNewAppRequest = isThisACreateNewAppRequest(pathToJavaFileToModify, contentOfExistingJavaFile);
- CodeGeneratorConfig codeGeneratorConfig = new CodeGeneratorConfig();
- Options options =
- new OptionsBuilder()
- .setNumCtx(codeGeneratorConfig.getNUM_CTX())
- .setTopK(codeGeneratorConfig.getTOP_K())
- .setNumPredict(codeGeneratorConfig.getNUM_PREDICT())
- .setTemperature(codeGeneratorConfig.getTEMPERATURE())
- .build();
+ boolean isThisNewAppRequest = isThisACreateNewAppRequest(pathToJavaFileToModify, contentOfExistingJavaFile);
PromptBuilder promptBuilder;
if (isThisNewAppRequest) {
promptBuilder = new PromptBuilder()
- .addLine(QuestionConstants.GREETING_TO_MODEL)
+ .addLine(GREETING_TO_MODEL)
.addLine(question)
.addLine(QuestionConstants.WITH_MAIN_METHOD)
.addLine(QuestionConstants.AND_CORRECT_IMPORTS)
@@ -76,7 +88,7 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil
} else {
promptBuilder = new PromptBuilder()
- .addLine(QuestionConstants.GREETING_TO_MODEL)
+ .addLine(GREETING_TO_MODEL)
.addLine(QuestionConstants.THANKS_FOR_ALL_GENERATED_APPS)
.addLine(QuestionConstants.FUNCTIONALITY_NEEDED);
@@ -100,15 +112,14 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil
.addLine(QuestionConstants.ONLY_CODE);
}
- api.setRequestTimeoutSeconds(100000);
- log.info("Is OLLAMA server alive? -> {}", api.ping()); // This is your local OLLAMA server running on localhost and is used for the LLM model
+
OllamaResult result = null;
try {
result = api.generate(codeGeneratorConfig.getOllamaModel(), promptBuilder.build(), options);
} catch (OllamaBaseException | IOException | InterruptedException e) {
- e.printStackTrace();
+ log.error("Error while sending a request to the local Ollama Server");
}
if (result == null) throw new AssertionError();
String outputFromOllamaAPI = (result.getResponse());
@@ -116,6 +127,174 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil
return outputFromOllamaAPI;
}
+ @Override
+ public List sendClassesNeededForSuperAppQuestionToOllamaInstance(String question) {
+
+ String responseFromAiModel = GetListOfClasses(question);
+
+ // Resend the question if validation fails (With recursive strategy)
+ if (responseFromAiModel.isEmpty() ||
+ !(CodeGeneratorUtil.ValidateResponseOnSuperAppGetAllClassesQuestion(responseFromAiModel))){
+ sendClassesNeededForSuperAppQuestionToOllamaInstance(question);}
+
+ // Convert response into list format
+ List classNames = StringUtil.GetListOfClassNamesInSuperAppGeneration(responseFromAiModel);
+
+ // Resend the question (Extra validation after method invocation)
+ if(classNames.size() < 2){
+ sendClassesNeededForSuperAppQuestionToOllamaInstance(question);
+ }
+
+ List unimplementedSuperAppClasses = CodeGeneratorUtil.convertListOfStringClassNamesIntoAnListOfUnimplementedSuperAppClasses(classNames);
+
+ // (Extra validation after method invocation)
+ if(unimplementedSuperAppClasses.size() < 2) {
+ sendClassesNeededForSuperAppQuestionToOllamaInstance(question);
+ }
+
+ return unimplementedSuperAppClasses;
+ }
+
+ @Override
+ public String sendSuperAppQuestionToOllamaInstance(SuperApp superAppClass) {
+ PromptBuilder promptBuilder;
+ List superAppList = DataStorage.getInstance().getListOfCurrentSuperAppClasses();
+
+ // Include the main method in the Main class
+ if (superAppClass.getClassName().equals("Main") || superAppClass.getClassName().equalsIgnoreCase("MainClass")) {
+
+ // Always include
+ promptBuilder = new PromptBuilder()
+ .addLine(GREETING_TO_MODEL)
+ .addLine(PROVIDE_ME_JAVA_CODE_SUPER_APP_SPECIFIC + superAppClass.getClassName())
+ .addLine(IMPLEMENT_MAIN_CLASS_IN_SUPER_APP_CREATION)
+ .addLine(AND_CORRECT_IMPORTS);
+
+
+ // At last one class has been implemented
+ if (superAppList.stream().anyMatch(SuperApp::isImplemented)) {
+ promptBuilder.addLine(MAKE_SURE_IT_ALIGNS_WITH_OTHER_CLASSES);
+ superAppList.stream().filter(SuperApp::isImplemented).forEach(s -> promptBuilder
+ .add(GetFormattedStringForAClassName(s) + CodeGeneratorUtil.GetFormattedListOfMethodsString(s)
+ + CodeGeneratorUtil.GetFormattedListOfConstructorString(s)));
+ promptBuilder.addLine(THAT_WAS_THE_LAST_LINE_OF_REMEMBER_CLASSES)
+ .addLine(QuestionConstants.DO_NOT_ASSUME_THAT_CLASSES_CONTAINS_METHODS_OR_CONSTRUCTORS_THAT_THEY_DO_NOT);
+ }
+
+ // No class at all has been implemented
+ else {
+
+ promptBuilder.addLine(CONSIDER_ALL_CLASSES_IN_THIS_SUPER_APP_CREATION)
+ .addLine(CLASSES_THAT_ARE_INCLUDED_IN_THE_SUPER_APP)
+ .addLine(THE_UNIMPLEMENTED_CLASSES_OF_THE_SUPER_APP);
+
+ superAppList.stream().filter(s -> !(s.getClassName()
+ .equalsIgnoreCase(superAppClass.getClassName())))
+ .toList()
+ .forEach(c -> promptBuilder.addLine(c.getClassName()));
+ promptBuilder
+ .addLine(LAST_LINE_OF_UNIMPLEMENTED_CLASSES_OF_THE_SUPER_APP)
+ .addLine(QuestionConstants.DO_NOT_ASSUME_THAT_CLASSES_CONTAINS_METHODS_OR_CONSTRUCTORS_THAT_THEY_DO_NOT);
+ }
+ // Always include
+ promptBuilder
+ .addLine(QuestionConstants.AND_MAKE_SURE_CORRECT_NUMBER_OF_BRACE_BRACKETS_ARE_USED_AT_THE_END_OF_THE_JAVA_CODE)
+ .addLine(QuestionConstants.MARK_START_CHAR_DELIMITER)
+ .addLine(QuestionConstants.MARK_THE_END_CHAR_DELIMITER)
+ .addLine(QuestionConstants.MAKE_SURE_THAT_START_DELIMITER_CHAR_IS_USED_ONCE)
+ .addLine(QuestionConstants.MAKE_SURE_THAT_END_DELIMITER_CHAR_IS_USED_ONCE)
+ .addLine(QuestionConstants.NO_JAVA_FX)
+ .addLine(QuestionConstants.NO_SPECIAL_LIBRARIES)
+ .addLine(QuestionConstants.MAKE_SURE_IT_WORKS_ON_JAVA_19)
+ .addLine(QuestionConstants.IMPLEMENT_AS_MUCH_AS_POSSIBLE)
+ .addLine(QuestionConstants.THREAD_PACKAGE)
+ .addLine(QuestionConstants.ONLY_CODE);
+
+ }
+
+
+ // Use this block for all other classes
+ else {
+ // Always include
+ promptBuilder = new PromptBuilder()
+ .addLine(GREETING_TO_MODEL)
+ .addLine(PROVIDE_ME_JAVA_CODE_SUPER_APP_SPECIFIC + superAppClass.getClassName())
+ .addLine(QuestionConstants.AND_CORRECT_IMPORTS)
+ .addLine(NO_MAIN_CLASS_UNLESS_THE_CLASS_NAME_IS_MAIN)
+ .addLine(QuestionConstants.AND_MAKE_SURE_CORRECT_NUMBER_OF_BRACE_BRACKETS_ARE_USED_AT_THE_END_OF_THE_JAVA_CODE)
+ .addLine(QuestionConstants.MARK_START_CHAR_DELIMITER)
+ .addLine(QuestionConstants.MARK_THE_END_CHAR_DELIMITER)
+ .addLine(QuestionConstants.MAKE_SURE_THAT_START_DELIMITER_CHAR_IS_USED_ONCE)
+ .addLine(QuestionConstants.MAKE_SURE_THAT_END_DELIMITER_CHAR_IS_USED_ONCE);
+
+ // At last one class has been implemented
+ if (superAppList.stream().anyMatch(SuperApp::isImplemented)) {
+ promptBuilder.addLine(MAKE_SURE_IT_ALIGNS_WITH_OTHER_CLASSES);
+ superAppList.stream().filter(SuperApp::isImplemented).forEach(s -> promptBuilder.add(GetFormattedStringForAClassName(s)
+ + CodeGeneratorUtil.GetFormattedListOfMethodsString(s) + GetFormattedListOfConstructorString(s)));
+ promptBuilder
+ .addLine(THAT_WAS_THE_LAST_LINE_OF_REMEMBER_CLASSES)
+ .addLine(DO_NOT_ASSUME_THAT_CLASSES_CONTAINS_METHODS_OR_CONSTRUCTORS_THAT_THEY_DO_NOT);
+ }
+ // No class at all has been implemented
+ else {
+
+ promptBuilder.addLine(CONSIDER_ALL_CLASSES_IN_THIS_SUPER_APP_CREATION)
+ .addLine(CLASSES_THAT_ARE_INCLUDED_IN_THE_SUPER_APP)
+ .addLine(THE_UNIMPLEMENTED_CLASSES_OF_THE_SUPER_APP);
+
+ superAppList.stream().filter(s -> !(s.getClassName()
+ .equalsIgnoreCase(superAppClass.getClassName())))
+ .toList()
+ .forEach(c -> promptBuilder.addLine(c.getClassName()));
+ promptBuilder.addLine(LAST_LINE_OF_UNIMPLEMENTED_CLASSES_OF_THE_SUPER_APP);
+ }
+ // Always include
+ promptBuilder
+ .addLine(QuestionConstants.NO_JAVA_FX)
+ .addLine(QuestionConstants.NO_SPECIAL_LIBRARIES)
+ .addLine(QuestionConstants.MAKE_SURE_IT_WORKS_ON_JAVA_19)
+ .addLine(QuestionConstants.IMPLEMENT_AS_MUCH_AS_POSSIBLE)
+ .addLine(QuestionConstants.THREAD_PACKAGE)
+ .addLine(QuestionConstants.ONLY_CODE);
+ }
+
+ OllamaResult result = null;
+ try {
+ result = api.generate(codeGeneratorConfig.getOllamaModel(), promptBuilder.build(), options);
+
+ } catch (OllamaBaseException | IOException | InterruptedException e) {
+ log.error("Error while sending a request to the local Ollama Server");
+ }
+ if (result == null) throw new AssertionError();
+ String outputFromOllamaAPI = (result.getResponse());
+ log.info(outputFromOllamaAPI);
+ return outputFromOllamaAPI;
+ }
+
+ private String GetListOfClasses(String question) {
+
+ List classNames = new LinkedList<>();
+ PromptBuilder initialPrompt = new PromptBuilder().addLine(QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX)
+ .addLine(question)
+ .addLine(QuestionConstants.LAST_LINE_OF_SUPER_APP)
+ .addLine(QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1)
+ .addLine(QuestionConstants.ONLY_CLASS_NAMES_IN_ANSWER)
+ .addLine(QuestionConstants.CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE)
+ .addLine(QuestionConstants.MAIN_CLASS_SHOULD_ALWAYS_BE_ADDED_TO_THE_CLASS_LIST);
+
+ OllamaResult result = null;
+ try {
+ result = api.generate(codeGeneratorConfig.getOllamaModel(), initialPrompt.build(), options);
+
+
+ } catch (OllamaBaseException | IOException | InterruptedException e) {
+ log.error("Error when sending the request to the local ollama server");
+ }
+
+ return result.getResponse();
+
+ }
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/CompileClassTask.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/CompileClassTask.java
index 09c0695..db0b563 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/CompileClassTask.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/CompileClassTask.java
@@ -44,8 +44,8 @@ private void handleConsoleOutput(String javacOutput) {
/**
* Set compilation job to status successful,and add the value to the shared singleton
*/
- private void successFullCompilation() {
- log.debug("successFullCompilation");
+ private synchronized void successFullCompilation() {
+ log.info("successFullCompilation");
CompilationJob compilationJob = new CompilationJob(assumedClassName);
compilationJob.setResult(true);
compilationJob.setErrorMessage(null);
@@ -56,8 +56,8 @@ private void successFullCompilation() {
/**
* Set compilation job to status error,and adds the sanitized error String to the shared singleton
*/
- private void compilationError(String javacOutput) {
- log.debug("compilationError");
+ private synchronized void compilationError(String javacOutput) {
+ log.info("compilationError");
CompilationJob compilationJob = new CompilationJob(assumedClassName);
compilationJob.setResult(false);
compilationJob.setErrorMessage(StringUtil
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/base/ScriptTask.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/base/ScriptTask.java
index 5f92516..ce6cdef 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/base/ScriptTask.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/task/base/ScriptTask.java
@@ -39,18 +39,9 @@ public ScriptTask(String scriptName, String[] inputArgs) {
protected String RunScript() {
- boolean isLinux = Objects.equals(File.separator, "/");
-
- String logMessage = isLinux ? "Started Shell Script Task" : "Started PS Script Task";
-
- log.debug(logMessage);
-
pb = new ProcessBuilder();
- if(isLinux)
SetCommandsLinux(pb);
- else
- SetCommandsWin(pb);
try {
@@ -96,22 +87,4 @@ protected void SetCommandsLinux(ProcessBuilder pb) {
}
- protected void SetCommandsWin(ProcessBuilder pb) {
-
- List cmdList = new LinkedList<>();
-
- String PS = "powershell.exe";
- cmdList.add(PS);
-
- cmdList.add(PATH_TO_SCRIPT);
-
- if (inputArgs != null)
- cmdList.add("-pathToJavaFile "+"\""+inputArgs[0]+"\"") ;
-
-
- pb.command(cmdList);
-
-
- }
-
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java
index 8fa4596..0f9b3d0 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java
@@ -1,15 +1,338 @@
package pn.cg.util;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import pn.cg.app_system.code_generation.model.SuperApp;
+import pn.cg.app_system.code_generation.model.enum_.OPTION_METHOD_CONSTRUCTOR;
+import pn.cg.datastorage.DataStorage;
+import pn.cg.datastorage.ThreadPoolMaster;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.LinkedList;
import java.util.List;
+import java.util.NoSuchElementException;
+
+import static pn.cg.datastorage.constant.ScriptConstants.COMPILE_CLASS_STORAGE;
-public class CodeGeneratorUtil {
+public record CodeGeneratorUtil() {
+
+ private static final Logger log = LoggerFactory.getLogger(CodeGeneratorUtil.class);
/**
* Boolean method that checks if it's a new request or a continues app generation
* Return false means that the request is sent to query the LLM Model further about an existing app
*/
- public static boolean isThisACreateNewAppRequest(String pathToJavaFileToModify, List contentOfExistingJavaFile){
+ public static boolean isThisACreateNewAppRequest(String pathToJavaFileToModify, List contentOfExistingJavaFile) {
return (contentOfExistingJavaFile == null || contentOfExistingJavaFile.size() <= 1 || pathToJavaFileToModify == null);
}
-}
+
+ /**
+ * Converts a list of class names into unimplemented classes in the current super app generation
+ *
+ * @param classNames A list of strings that contains class names needed for the current super app generation
+ * @return List
+ */
+ public static List convertListOfStringClassNamesIntoAnListOfUnimplementedSuperAppClasses(List classNames) {
+
+ List superAppList = new LinkedList<>();
+ classNames.forEach(className -> superAppList.add(new SuperApp(className, false)));
+
+ return superAppList;
+ }
+
+ /**
+ * Check the implementation status of the entire super app creation
+ *
+ * @param classList List of classes for the super app creation and their implementation status
+ * @return true if all classes are implemented , else false
+ */
+ public static boolean areAllSuperClassesImplemented(List classList) {
+ return classList.stream().filter(superAppClass -> !superAppClass.isImplemented()).toList().isEmpty();
+ }
+
+ /**
+ * Get a random unimplemented class from the input list
+ *
+ * @return A random SuperApp from the input list with a status of unimplemented (if any)
+ */
+ public static SuperApp getARandomUnimplementedClass() throws NoSuchElementException {
+
+ return DataStorage.getInstance().getListOfCurrentSuperAppClasses().stream().filter(e -> !e.isImplemented()).findAny().orElseThrow();
+ }
+
+ /**
+ * Read the files in the COMPILE_CLASS_STORAGE folder and filter the current super apps directories and increment the number by one
+ *
+ * @return String
+ */
+ public static String getIncrementedSuperAppDirectoryName() {
+ final String SUPER_APP_FOLDER_NAME = "APP_";
+
+ // The number that will be appended to the APP_ directory
+ int appNumber = 1;
+
+ //Placeholder list that will be filled with the appending number of existing APP_ directories (if any)
+ List listOfNumbersThatAreAppendedToExistingSuperAppsDirectories = new LinkedList<>();
+
+ try {
+ List superAppFolders = Files.list(new File(COMPILE_CLASS_STORAGE)
+ .toPath())
+ .filter(file -> file.getFileName()
+ .toString()
+ .startsWith(SUPER_APP_FOLDER_NAME))
+ .toList();
+
+ if (superAppFolders.isEmpty()) {
+ return SUPER_APP_FOLDER_NAME + appNumber;
+ } else {
+
+ superAppFolders.forEach(p -> listOfNumbersThatAreAppendedToExistingSuperAppsDirectories
+ .add(Integer.parseInt(p.getFileName().toString().split(SUPER_APP_FOLDER_NAME)[1])));
+
+ // Take the highest and increment it by one
+ int maxNumberOfExistingSuperAppDirectories = listOfNumbersThatAreAppendedToExistingSuperAppsDirectories
+ .stream()
+ .mapToInt(Integer::intValue)
+ .max()
+ .getAsInt();
+
+ return SUPER_APP_FOLDER_NAME + (maxNumberOfExistingSuperAppDirectories + 1);
+ }
+
+ } catch (NumberFormatException | IOException e) {
+ log.error("You have a folder in the that resides in the directory for the generated java applications that starts with \"APP_\" and have a suffix that is not an Integer\nPlease move or delete that folder to resolve this error");
+ ThreadPoolMaster.getInstance().TerminateThreads();
+ System.exit(1);
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ /**
+ * Set the method list for an implemented SuperApp class in the shared singleton list
+ *
+ * @param implementedClassName The name of the implemented class
+ * @param pathToJavaClassDirectory The path to the directory where the class file is resided
+ */
+ public static void SetMethodAndConstructorListForImplementedClass(String implementedClassName, Path pathToJavaClassDirectory) throws MalformedURLException, ClassNotFoundException {
+
+ try {
+ SuperApp superapp = DataStorage.getInstance()
+ .getListOfCurrentSuperAppClasses()
+ .stream()
+ .filter(s -> s.getClassName()
+ .equals(implementedClassName))
+ .findFirst()
+ .get();
+
+ superapp.setMethods(ExtractDeclaredMethodsFromClassFile(implementedClassName, pathToJavaClassDirectory));
+ superapp.setConstructors(ExtractDeclaredConstructorsFromClassFile(implementedClassName, pathToJavaClassDirectory));
+ } catch (Exception e) {
+ log.error("Could not set Method and/or Constructors for a compiled class...");
+ }
+
+ }
+
+ /**
+ * Checks if all classes in the super app creation are unimplemented
+ *
+ * @param superAppList A list that contains SuperApp instances
+ * @return boolean
+ */
+ public static boolean AreAllClassesUnImplemented(List superAppList) {
+
+ if (superAppList != null) return superAppList.stream().anyMatch(SuperApp::isImplemented);
+ return false;
+ }
+
+ /**
+ * Get a formatted String that will differ depending on wherever the super app contains methods or not
+ *
+ * @param superApp A SuperApp instance
+ * @return String
+ * @Format-Style A String that is formatted for a query to an AI-Model
+ */
+ public static String GetFormattedListOfMethodsString(SuperApp superApp) {
+
+ if (superApp.getMethods() == null)
+ superApp.setMethods(new LinkedList<>());
+
+ if (superApp.getMethods().isEmpty())
+ return " ,with no public methods";
+ else
+ return " ,with methods: " + superApp.toStringForMethods();
+ }
+
+ /**
+ * Get a formatted String that will differ depending on wherever the super app contains constructors or not
+ *
+ * @param superApp A SuperApp instance
+ * @return String
+ * @Format-Style A String that is formatted for a query to an AI-Model
+ */
+ public static String GetFormattedListOfConstructorString(SuperApp superApp) {
+
+ if (superApp.getConstructors() == null)
+ superApp.setConstructors(new LinkedList<>());
+
+ if (superApp.getConstructors().isEmpty())
+ return ", " + "and it does not have any public constructors";
+ else return ", " + " and constructors: " + superApp.toStringForConstructors() + ",";
+ }
+
+ /**
+ * Get a formatted String for a class name
+ *
+ * @param superApp A SuperApp instance
+ * @return String
+ * @Format-Style A String that is formatted for a query to an AI-Model or for writing to a doc file
+ */
+ public static String GetFormattedStringForAClassName(SuperApp superApp) {
+ return "\nClass name: " + superApp.getClassName();
+ }
+
+ /**
+ * Writes the documentation for the super app creation to a file
+ *
+ * @param successfulSuperAppCreation A list that only should contain
+ * implemented classes in a successful super app creation
+ * @param file The file that the documentation data shall be written to
+ * @return boolean
+ */
+ public static boolean WriteDocFileToSuperApp(List successfulSuperAppCreation, File file) {
+
+ final StringBuilder formatStringBuilder = new StringBuilder();
+
+ formatStringBuilder.append("App Documentation\n");
+
+ successfulSuperAppCreation.forEach(s -> formatStringBuilder
+ .append("\n------------------")
+ .append(GetFormattedStringForAClassName(s))
+ .append("\n")
+ .append(GetFormattedListOfMethodsStringForDocFile(s))
+ .append("\n")
+ .append(GetFormattedListOfConstructorStringForDocFile(s)));
+ try {
+ FileUtil.writeDataToFile(file, formatStringBuilder.toString());
+ return true;
+ } catch (IOException e) {
+ log.error("Could not write the documentation for this app to a file...");
+ }
+ return false;
+ }
+
+ /**
+ * Gets the path in text format to the current super app directory
+ * @return String
+ */
+ public static String GetDocFilePathForSuperApp(){
+
+ final String DOC_FILE_FOR_SUPER_APP_PATH = COMPILE_CLASS_STORAGE + File.separator + DataStorage.getInstance().getSuperAppDirectoryName()+File.separator+"DOCS.txt";
+ return DOC_FILE_FOR_SUPER_APP_PATH;
+ }
+
+ /**
+ * Validate the response on a "Get All Classes" question to an AI-Model
+ * @param responseFromAiModelOnGetAllClassesFromSuperAppQuestion Response from AI-Model
+ * @return boolean
+ */
+ public static boolean ValidateResponseOnSuperAppGetAllClassesQuestion(String responseFromAiModelOnGetAllClassesFromSuperAppQuestion){
+
+ return !responseFromAiModelOnGetAllClassesFromSuperAppQuestion.contains(" ")
+ && !responseFromAiModelOnGetAllClassesFromSuperAppQuestion.contains(":")
+ && !responseFromAiModelOnGetAllClassesFromSuperAppQuestion.contains(",");
+
+ }
+ /**
+ * Get a formatted String that will differ depending on wherever the super app contains methods or not
+ *
+ * @param superApp A SuperApp instance
+ * @return String
+ * @Format-Style A String that is formatted for writing to a doc file
+ */
+ private static String GetFormattedListOfMethodsStringForDocFile(SuperApp superApp) {
+
+ if (superApp.getMethods() == null)
+ superApp.setMethods(new LinkedList<>());
+
+ if (superApp.getMethods().isEmpty())
+ return "No public methods";
+ else
+ return "Public Methods: " + superApp.toStringForMethods();
+ }
+
+
+ /**
+ * Get a formatted String that will differ depending on wherever the super app contains constructors or not
+ *
+ * @param superApp A SuperApp instance
+ * @return String
+ * @Format-Style A String that is formatted for writing to a doc file
+ */
+ private static String GetFormattedListOfConstructorStringForDocFile(SuperApp superApp) {
+
+ if (superApp.getConstructors() == null)
+ superApp.setConstructors(new LinkedList<>());
+
+ if (superApp.getConstructors().isEmpty())
+ return "No public constructors";
+ else return "Public Constructors: " + superApp.toStringForConstructors();
+ }
+
+ private static List ExtractDeclaredConstructorsFromClassFile(String className, Path pathToClassFileDirectory) throws MalformedURLException, ClassNotFoundException {
+ return ExtractDeclared(className, pathToClassFileDirectory, OPTION_METHOD_CONSTRUCTOR.CONSTRUCTOR);
+ }
+
+ private static List ExtractDeclaredMethodsFromClassFile(String className, Path pathToClassFileDirectory) throws MalformedURLException, ClassNotFoundException {
+
+ return ExtractDeclared(className, pathToClassFileDirectory, OPTION_METHOD_CONSTRUCTOR.METHOD);
+ }
+
+ private static List ExtractDeclared(String className, Path pathToClassFileDirectory, OPTION_METHOD_CONSTRUCTOR option) throws MalformedURLException, ClassNotFoundException {
+
+ List returnList = new LinkedList<>();
+
+ String filePath = pathToClassFileDirectory.toString() + className + ".class"; // Replace with the actual path to your class
+
+ File file = new File(filePath);
+ URL url = file.getParentFile().toURI().toURL();
+ URLClassLoader loader = new URLClassLoader(new URL[]{url});
+
+ Class> clazz = loader.loadClass(className);
+
+ if (option == OPTION_METHOD_CONSTRUCTOR.METHOD) {
+ System.out.println("Public methods:");
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (Modifier.isPublic(method.getModifiers())) {
+ System.out.println(method.toString());
+ returnList.add(method.toString());
+
+ }
+ }
+
+ return returnList;
+ } else if (option == OPTION_METHOD_CONSTRUCTOR.CONSTRUCTOR) {
+ System.out.println("\nPublic constructors:");
+ for (Constructor> constructor : clazz.getConstructors()) {
+ if (Modifier.isPublic(constructor.getModifiers())) {
+ System.out.println(constructor.toString());
+ returnList.add(constructor.toString());
+ }
+ }
+
+ return returnList;
+ }
+ // Return empty list
+ return returnList;
+ }
+}
\ No newline at end of file
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java
index aa19ebd..774d715 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java
@@ -5,6 +5,12 @@
import org.slf4j.LoggerFactory;
import pn.cg.datastorage.constant.CommonStringConstants;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import static pn.cg.util.CodeGeneratorUtil.ValidateResponseOnSuperAppGetAllClassesQuestion;
+
public class StringUtil {
@@ -76,6 +82,7 @@ public static String getFirstLine(String input) {
/**
* Removes chars that might cause ollama´s api to send 400
+ *
* @param input input String
* @return String
*/
@@ -156,7 +163,9 @@ private static String removeDelimiters(String input, boolean isStartDelimiter) {
} else if (!isStartDelimiter) {
delimiter = CommonStringConstants.JAVA_CODE_GENERATION_END_DELMITER_STRING;
returnValue = RemoveAllExceptTheLastOccurrenceOfWord(returnValue, delimiter);
- returnValue = RemoveAllExceptTheLastOccurrenceOfWord(returnValue,delimiter+"\n");
+
+ returnValue = RemoveAllExceptTheLastOccurrenceOfWord(returnValue, delimiter + "\n");
+
}
} catch (Exception e) {
log.debug("Error on delimiter String removal process");
@@ -177,7 +186,7 @@ public static int GetUnbalancedBraceBracketsFromString(String input) {
/**
* Appends brace buckets at the end of the String
*
- * @param input String Input
+ * @param input String Input
* @param numberOfBraceBuckets int
* @return input string appended with the given amount of brace buckets
*/
@@ -207,19 +216,50 @@ public static String RemoveCommonAdditionStringsFromAiModels(String input) {
try {
returnValue = returnValue.replace("```java", "")
.replace("```", "")
- .replace("```Java","")
- .replace("```JAVA","");
+ .replace("```Java", "")
+ .replace("```JAVA", "");
} catch (Exception e) {
- log.debug("Could not remove common addition string");
+ log.error("Could not remove common addition string");
}
return returnValue;
}
+ /**
+ * Takes an input string formated with new lines , parses it , and then converts it into a list
+ *
+ * @param input A string with class names delimited with new lines
+ * @return List
+ */
+ public static List GetListOfClassNamesInSuperAppGeneration(String input) {
+ try {
+ String[] classNamesArr = input.split("\n");
+ List tmpClassNames = new LinkedList<>();
+
+ for (String className : classNamesArr) {
+ if (!className.contains(" ")
+ || !className.equals("\n")
+ || !Character.isLowerCase(className.codePointAt(0))
+ && (className.matches("^[a-z\nA-Z]+$") || className.matches("^[0-9\n]+$"))) {
+
+ if(!className.equalsIgnoreCase("\n")){
+ tmpClassNames.add(className);}
+ }
+ }
+
+ return tmpClassNames.stream().filter(line -> !(line.contains(" "))).toList();
+
+ } catch (Exception e) {
+
+ log.error("Could not extract class names from the response from the AI-model");
+ }
+ return new LinkedList<>();
+ }
+
/**
* Replace all occurrences (with an empty String) except the first one of the delimiter word
*
- * @param input input String
+ * @param input input String
* @param delimiter delimiter String
*/
private static String RemoveAllExceptTheFirstOccurrenceOfaAWord(String input, String delimiter) {
@@ -234,7 +274,7 @@ private static String RemoveAllExceptTheFirstOccurrenceOfaAWord(String input, St
/**
* Replace all occurrences (with an empty String) except the last one of the delimiter word
*
- * @param input input String
+ * @param input input String
* @param delimiter String
*/
private static String RemoveAllExceptTheLastOccurrenceOfWord(String input, String delimiter) {
@@ -248,4 +288,6 @@ private static String RemoveAllExceptTheLastOccurrenceOfWord(String input, Strin
return cleanedBeforerEndDelimiterString.concat(lastPart);
}
+
+
}
\ No newline at end of file
diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java
index 8915d39..6e56531 100644
--- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java
+++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java
@@ -3,16 +3,30 @@
import pn.cg.datastorage.constant.ScriptConstants;
import java.io.File;
+import java.nio.file.Path;
-public class TaskUtil {
+public record TaskUtil() {
/**
- * Adds the file path to the Java source code folder
- * @param classname
- * @return
+ * Adds the class name to the path of the Java source code folder
+ * @param className Name of the class
+ * @return String
*/
- public static String addFilePathToClassName(String classname){
+ public static String addFilePathToClassName(String className){
- return ScriptConstants.COMPILE_CLASS_STORAGE+ File.separator+classname;
+ return ScriptConstants.COMPILE_CLASS_STORAGE+ File.separator+className;
}
+
+ /**
+ * Adds the class name to the path of super app directory
+ * @param className Name of the class
+ * @param superAppDirectory Name of the directory for the super app
+ * @return String
+ */
+ public static String addFilePathOfSuperAppToClassName(String className, String superAppDirectory){
+
+ return ScriptConstants.COMPILE_CLASS_STORAGE+File.separator+superAppDirectory+File.separator +className;
+
+ }
+
}
diff --git a/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java b/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java
index 12cda5b..a0d019a 100644
--- a/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java
+++ b/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java
@@ -4,6 +4,9 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import java.util.Arrays;
+import java.util.List;
+
public class StringUtilTest {
@Test
@@ -274,9 +277,7 @@ public void RemoveExtraStartDelimitersInResponseTest() {
public void removeExtraEndDelimitersInResponseTest() {
final String TEST_TEXT = "@START_HERE javacode1.. more java code2... @END_HERE more javacode3.... @END_HERE";
-
final String expected = "@START_HERE javacode1.. more java code2... more javacode3.... @END_HERE";
-
final String actual = StringUtil.RemoveExtraEndDelimitersInResponse(TEST_TEXT);
Assertions.assertEquals(expected, actual);
@@ -288,9 +289,7 @@ public void removeExtraEndDelimitersInResponseTest() {
public void getUnbalancedBraceBracketsFromStringTest() {
final int expected = 1;
-
final String text = "public class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }";
-
final int actual = StringUtil.GetUnbalancedBraceBracketsFromString(text);
Assertions.assertEquals(expected, actual);
@@ -301,9 +300,7 @@ public void RemoveCommonAdditionStringsFromAiModelsTest() {
final String text = "```java\npublic class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }}\n```";
-
final String expected = "\npublic class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }}\n";
-
final String actual = StringUtil.RemoveCommonAdditionStringsFromAiModels(text);
Assertions.assertEquals(expected, actual);
@@ -314,12 +311,34 @@ public void AppendWithCorrectNumberOfBraceBucketsAtEndOfTheString() {
final String text = "public class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }";
-
final String expected = "public class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }}";
-
final String actual = StringUtil.AppendBraceBucketsAtEndofTheString(text, StringUtil.GetUnbalancedBraceBracketsFromString(text));
Assertions.assertEquals(expected, actual);
}
+ @Test
+ public void ConvertStringWithClassNamesIntoAListTest(){
+
+ final String text ="Jframe\nAccount\nMain";
+ final int expected=3;
+ final int actual = StringUtil.GetListOfClassNamesInSuperAppGeneration(text).size();
+
+ Assertions.assertEquals(expected,actual);
+ }
+
+ @Test
+ public void GetListOfClassNamesInSuperAppGenerationTest(){
+
+ final String TEST_INPUT="Here are the class names for your application:\n\nQuestionClass\nAnswerClass\nUserClass\nQuestionServiceClass\nAnswerServiceClass\nUserServiceClass\nMainClass";
+
+ final String PERFECT_RESPONSE_FROM_AI_MODEL="\nQuestionClass\nAnswerClass\nUserClass\nQuestionServiceClass\nAnswerServiceClass\nUserServiceClass\nMainClass";
+
+
+ final List EXPECTED = Arrays.stream(PERFECT_RESPONSE_FROM_AI_MODEL.split("\n")).toList();
+ final List ACTUAL = StringUtil.GetListOfClassNamesInSuperAppGeneration(TEST_INPUT);
+
+ Assertions.assertEquals(EXPECTED,ACTUAL);
+ }
+
}
\ No newline at end of file