diff --git a/pom.xml b/pom.xml
index 6086b25..6502c12 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,12 @@
21
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
org.springframework.boot
spring-boot-starter-data-jpa
diff --git a/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java b/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java
index 250b57b..1ddabd0 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/WorkflowManagerApplication.java
@@ -1,25 +1,17 @@
package it.cnr.isti.workflow.manager;
import java.util.List;
-import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
-import org.springframework.util.ResourceUtils;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
import it.cnr.isti.workflow.manager.executors.ai.models.AIModel;
-import it.cnr.isti.workflow.manager.model.auth.LoginEntity;
-import it.cnr.isti.workflow.manager.model.flows.Flow;
import it.cnr.isti.workflow.manager.model.types.IOType;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
-import it.cnr.isti.workflow.manager.model.types.ParameterDefinition;
-import it.cnr.isti.workflow.manager.model.types.ParameterType;
-import it.cnr.isti.workflow.manager.model.types.Translator;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.InputNodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
import it.cnr.isti.workflow.manager.repositories.AuthRepository;
import it.cnr.isti.workflow.manager.repositories.FlowRepository;
import it.cnr.isti.workflow.manager.repositories.NodeDefinitionRepository;
@@ -39,72 +31,13 @@ public class WorkflowManagerApplication {
CommandLineRunner init(NodeDefinitionRepository repository, FlowRepository flowRepository, AuthRepository authRepository) {
return args -> {
- JSONObject rPars = new JSONObject().put("options",
- aiModels.stream().map(AIModel::getName).toList());
-
- ParameterDefinition rgParams = ParameterDefinition.builder().name("LLM").type(ParameterType.Select)
- .label("Select the LLM to use").description("The LLM to use for generating requirements")
- .required(true).specificAttributes(rPars).build();
-
- JSONObject languageOptions = new JSONObject().put("options",
- List.of("Franch", "English", "Italian", "spanish", "German", "Chinese", "Japanese"));
- ParameterDefinition langParam = ParameterDefinition.builder().name("language").type(ParameterType.Select)
- .label("Language").description("The language to translate to").required(true)
- .specificAttributes(languageOptions).build();
+ NodeDefinition textInput = InputNodeDefinition.builder().name("Text Input")
+ .createdBy("admin").category("Inputs").outputType(IOType.Text)
+ .build();
- Translator inputTranslator = Translator.builder()
- .translation("translate the following phrase ${{phrase}} to ${{language}} returning only the translated").build();
-
- NodeDefinition translator = NodeDefinition.builder().type("Translator")
- .executor("GENERIC-AI").createdBy("admin").category("Translator")
- .input("phrase",IOType.Text).output("translated",IOType.Text)
- .runtimeParameter("LLM", rgParams).runtimeParameter("language", langParam)
- .executorToOutputTranslationMapping("response", "translated")
- .inputTranslator("prompt", inputTranslator).build();
-
-
- repository.save(translator);
- /*
- loadNodeDefinitionAndSave(repository);
-
- loadFlowsAndSave(flowRepository);
-
- insertUser(authRepository);
- */
+ repository.save(textInput);
};
}
- private void loadNodeDefinitionAndSave(NodeDefinitionRepository repository) {
- ObjectMapper objectMapper = new ObjectMapper();
-
- try{
-
- List nodes = objectMapper.readValue(ResourceUtils.getFile("classpath:saved-node-type.json"), objectMapper.getTypeFactory().constructCollectionType(List.class,NodeDefinition.class));
- for (NodeDefinition node: nodes)
- repository.save(node);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void loadFlowsAndSave(FlowRepository repository) {
- ObjectMapper objectMapper = new ObjectMapper();
-
- try{
-
- List flows = objectMapper.readValue(ResourceUtils.getFile("classpath:flows.json"), objectMapper.getTypeFactory().constructCollectionType(List.class,Flow.class));
- for (Flow flow: flows){
- repository.save(flow);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private void insertUser(AuthRepository repository) {
- LoginEntity le = new LoginEntity("lucio.lelii", "lucio");
- repository.save(le);
- }
-
}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java b/src/main/java/it/cnr/isti/workflow/manager/controllers/nodes/NodeDefinitionController.java
similarity index 84%
rename from src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java
rename to src/main/java/it/cnr/isti/workflow/manager/controllers/nodes/NodeDefinitionController.java
index 370ea1a..1b18b74 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/controllers/NodeDefinitionController.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/controllers/nodes/NodeDefinitionController.java
@@ -1,4 +1,4 @@
-package it.cnr.isti.workflow.manager.controllers;
+package it.cnr.isti.workflow.manager.controllers.nodes;
import java.util.List;
@@ -13,7 +13,8 @@ import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import it.cnr.isti.workflow.manager.executors.Executor;
import it.cnr.isti.workflow.manager.model.ExecutorDescriptor;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.UserNodeDefinition;
import it.cnr.isti.workflow.manager.repositories.NodeDefinitionRepository;
@RestController
@@ -28,7 +29,7 @@ public class NodeDefinitionController {
@Autowired
private List executors;
- @SecurityRequirement(name = "bearerAuth")
+ //@SecurityRequirement(name = "bearerAuth")
@GetMapping("/nodes")
public List getNodes() {
return (List) repository.findAll();
@@ -49,7 +50,7 @@ public class NodeDefinitionController {
@SecurityRequirement(name = "bearerAuth")
@PostMapping("/nodes")
- void addNode(@RequestBody NodeDefinition node) {
+ void addNode(@RequestBody UserNodeDefinition node) {
repository.save(node);
}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/exceptions/GlobalExceptionHandler.java b/src/main/java/it/cnr/isti/workflow/manager/exceptions/GlobalExceptionHandler.java
index e718780..8b903f7 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/exceptions/GlobalExceptionHandler.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/exceptions/GlobalExceptionHandler.java
@@ -9,6 +9,8 @@ import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class GlobalExceptionHandler {
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity handleNotFound(ResourceNotFoundException ex, WebRequest request) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
@@ -23,6 +25,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity handleGenericException(Exception ex) {
+ log.error("unexpected error", ex);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An unexpected error occurred: " + ex.getMessage());
diff --git a/src/main/java/it/cnr/isti/workflow/manager/model/ExecutionStep.java b/src/main/java/it/cnr/isti/workflow/manager/model/ExecutionStep.java
index 686102e..22f0d18 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/model/ExecutionStep.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/model/ExecutionStep.java
@@ -13,8 +13,9 @@ import org.slf4j.Logger;
import it.cnr.isti.workflow.manager.exceptions.ExecutionException;
import it.cnr.isti.workflow.manager.executors.Executor;
import it.cnr.isti.workflow.manager.model.ExecutionContext.Status;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
import it.cnr.isti.workflow.manager.model.types.Translator;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.UserNodeDefinition;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -47,12 +48,12 @@ public class ExecutionStep implements InputReadyListener {
//List previouSteps = new ArrayList<>();
@NonNull
- NodeDefinition nodeDefinition;
+ UserNodeDefinition nodeDefinition;
@Builder
public ExecutionStep(ExecutionContext context, String id, Map runtimeParameters,
Map fixedParameters,
- NodeDefinition nodeDefinition,
+ UserNodeDefinition nodeDefinition,
Executor executor) {
this.id = id;
this.runtimeParameters = runtimeParameters;
@@ -79,7 +80,7 @@ public class ExecutionStep implements InputReadyListener {
if (areAllInputsReady())
new Thread(() -> {
this.context.getStepsUnderExecution().add(this.id);
- log.info("starting executing of step {}", this.nodeDefinition.getType());
+ log.info("starting executing of step {}", this.nodeDefinition.getName());
try {
Map realInputs = prepareInputs();
//log.debug("input translation for step {} is {}", id, realInputs);
@@ -105,7 +106,7 @@ public class ExecutionStep implements InputReadyListener {
return;
} finally {
this.context.getStepsUnderExecution().remove(this.id);
- log.info("finished executing of step {}", this.nodeDefinition.getType());
+ log.info("finished executing of step {}", this.nodeDefinition.getName());
}
}).start();
diff --git a/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/InputNodeDefinition.java b/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/InputNodeDefinition.java
new file mode 100644
index 0000000..f293a24
--- /dev/null
+++ b/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/InputNodeDefinition.java
@@ -0,0 +1,37 @@
+package it.cnr.isti.workflow.manager.model.types.nodes.definitions;
+
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+
+import it.cnr.isti.workflow.manager.model.types.IOType;
+import it.cnr.isti.workflow.manager.model.types.ParameterDefinition;
+import it.cnr.isti.workflow.manager.model.types.ParameterType;
+import jakarta.persistence.DiscriminatorValue;
+import jakarta.persistence.Entity;
+import lombok.Builder;
+import lombok.NoArgsConstructor;
+
+@Entity
+@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
+@DiscriminatorValue("1")
+public class InputNodeDefinition extends NodeDefinition {
+
+ @Builder
+ public InputNodeDefinition(String name, String createdBy, String category, IOType outputType) {
+ super();
+ this.setName(name);
+ this.setCreatedBy(createdBy);
+ this.setCategory(category);
+ this.outputs = Map.of("value", outputType);
+ this.setColor("blue");
+ this.runtimeParameters = Map.of("name", ParameterDefinition.builder()
+ .name("name")
+ .label("Input Name")
+ .description("Input name")
+ .type(ParameterType.Text)
+ .build());
+ }
+
+
+}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/NodeDefinition.java b/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/NodeDefinition.java
new file mode 100644
index 0000000..ed9e39c
--- /dev/null
+++ b/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/NodeDefinition.java
@@ -0,0 +1,81 @@
+package it.cnr.isti.workflow.manager.model.types.nodes.definitions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import it.cnr.isti.workflow.manager.model.types.IOType;
+import it.cnr.isti.workflow.manager.model.types.ParameterDefinition;
+import it.cnr.isti.workflow.manager.repositories.converters.IOTypeMapConverter;
+import it.cnr.isti.workflow.manager.repositories.converters.MapsConverter;
+import jakarta.persistence.Column;
+import jakarta.persistence.Convert;
+import jakarta.persistence.DiscriminatorColumn;
+import jakarta.persistence.DiscriminatorType;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Inheritance;
+import jakarta.persistence.InheritanceType;
+import jakarta.validation.constraints.NotBlank;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.Singular;
+import lombok.experimental.SuperBuilder;
+
+@Entity
+@Data
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn(name="node_type", length = 1,
+ discriminatorType = DiscriminatorType.INTEGER)
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = UserNodeDefinition.class)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = InputNodeDefinition.class, name = "input"),
+ @JsonSubTypes.Type(value = UserNodeDefinition.class, name = "user")
+})
+public abstract class NodeDefinition {
+
+ @Id
+ @NonNull
+ @NotBlank
+ private String name;
+
+ @NonNull
+ @NotBlank
+ private String createdBy;
+
+ @NonNull
+ @NotBlank
+ private String category;
+
+ @Builder.Default
+ private String color = "black";
+
+ @Builder.Default
+ @Convert(converter = MapsConverter.class)
+ @Column(columnDefinition = "TEXT")
+ private Map fixedParameters = new HashMap<>();
+
+ @Builder.Default
+ @Convert(converter = MapsConverter.class)
+ @Column(columnDefinition = "TEXT")
+ protected Map runtimeParameters = new HashMap<>();
+
+ @Singular
+ @Convert(converter = IOTypeMapConverter.class)
+ @Column(columnDefinition = "TEXT")
+ private Map inputs;
+
+ @Singular
+ @Convert(converter = IOTypeMapConverter.class)
+ @Column(columnDefinition = "TEXT")
+ protected Map outputs;
+
+}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/model/types/NodeDefinition.java b/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/UserNodeDefinition.java
similarity index 51%
rename from src/main/java/it/cnr/isti/workflow/manager/model/types/NodeDefinition.java
rename to src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/UserNodeDefinition.java
index b3fa315..f05226f 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/model/types/NodeDefinition.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/model/types/nodes/definitions/UserNodeDefinition.java
@@ -1,72 +1,35 @@
-package it.cnr.isti.workflow.manager.model.types;
+package it.cnr.isti.workflow.manager.model.types.nodes.definitions;
import java.util.Map;
-
-import it.cnr.isti.workflow.manager.repositories.converters.IOTypeMapConverter;
+import it.cnr.isti.workflow.manager.model.types.Translator;
import it.cnr.isti.workflow.manager.repositories.converters.InputTranslatorConverter;
import it.cnr.isti.workflow.manager.repositories.converters.MapsConverter;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
+import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.IdClass;
import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
-import lombok.Builder;
import lombok.Data;
+import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Singular;
-import lombok.Builder.Default;
+import lombok.experimental.SuperBuilder;
@Entity
-@Data
-@AllArgsConstructor
@NoArgsConstructor
-@Builder
-public class NodeDefinition {
-
- @Id
- @NonNull
- @NotBlank
- private String type;
-
- @NonNull
- @NotBlank
- private String createdBy;
-
- @NonNull
- @NotBlank
- private String category;
+@AllArgsConstructor
+@SuperBuilder
+@Data
+@EqualsAndHashCode(callSuper = true)
+@DiscriminatorValue("2")
+public class UserNodeDefinition extends NodeDefinition {
@NonNull
@NotBlank
private String executor;
- @Builder.Default
- private String color = "black";
-
- @Singular
- @Convert(converter = MapsConverter.class)
- @Column(columnDefinition = "TEXT")
- private Map fixedParameters;
-
- @Singular
- @Convert(converter = MapsConverter.class)
- @Column(columnDefinition = "TEXT")
- private Map runtimeParameters;
-
- @Singular
- @Convert(converter = IOTypeMapConverter.class)
- @Column(columnDefinition = "TEXT")
- private Map inputs;
-
- @Singular
- @Convert(converter = IOTypeMapConverter.class)
- @Column(columnDefinition = "TEXT")
- private Map outputs;
// contains the mapping of the result of the execution with the output of the
// node
@@ -86,5 +49,4 @@ public class NodeDefinition {
@Convert(converter = InputTranslatorConverter.class)
@Column(columnDefinition = "TEXT")
private Map inputTranslators;
-
}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/repositories/InputDefinitionRepository.java b/src/main/java/it/cnr/isti/workflow/manager/repositories/InputDefinitionRepository.java
new file mode 100644
index 0000000..9a98069
--- /dev/null
+++ b/src/main/java/it/cnr/isti/workflow/manager/repositories/InputDefinitionRepository.java
@@ -0,0 +1,10 @@
+package it.cnr.isti.workflow.manager.repositories;
+
+import org.springframework.data.repository.CrudRepository;
+
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.InputNodeDefinition;
+
+
+public interface InputDefinitionRepository extends CrudRepository {
+
+}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/repositories/NodeDefinitionRepository.java b/src/main/java/it/cnr/isti/workflow/manager/repositories/NodeDefinitionRepository.java
index 0777045..c83d059 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/repositories/NodeDefinitionRepository.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/repositories/NodeDefinitionRepository.java
@@ -6,12 +6,12 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
@Repository
public interface NodeDefinitionRepository extends CrudRepository {
- @Query("SELECT n.type FROM NodeDefinition n")
+ @Query("SELECT n.name FROM NodeDefinition n")
List getUsedTypes();
@Query("SELECT DISTINCT n.category FROM NodeDefinition n")
diff --git a/src/main/java/it/cnr/isti/workflow/manager/repositories/UserNodeDefinitionRepository.java b/src/main/java/it/cnr/isti/workflow/manager/repositories/UserNodeDefinitionRepository.java
new file mode 100644
index 0000000..4399f4b
--- /dev/null
+++ b/src/main/java/it/cnr/isti/workflow/manager/repositories/UserNodeDefinitionRepository.java
@@ -0,0 +1,9 @@
+package it.cnr.isti.workflow.manager.repositories;
+
+import org.springframework.data.repository.CrudRepository;
+
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.UserNodeDefinition;
+
+public interface UserNodeDefinitionRepository extends CrudRepository {
+
+}
diff --git a/src/main/java/it/cnr/isti/workflow/manager/services/ImportComponent.java b/src/main/java/it/cnr/isti/workflow/manager/services/ImportComponent.java
index b8d4932..aa4180b 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/services/ImportComponent.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/services/ImportComponent.java
@@ -7,13 +7,12 @@ import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
-import org.springframework.util.ResourceUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.cnr.isti.workflow.manager.model.auth.LoginEntity;
import it.cnr.isti.workflow.manager.model.flows.Flow;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
import it.cnr.isti.workflow.manager.repositories.AuthRepository;
import it.cnr.isti.workflow.manager.repositories.FlowRepository;
import it.cnr.isti.workflow.manager.repositories.NodeDefinitionRepository;
@@ -49,8 +48,6 @@ public class ImportComponent {
System.out.println("ImportComponent is disabled");
return;
}
- System.out.println("ImportComponent initialized");
- // Perform any initialization logic here
File flowsFile = new File(path, FLOW_FILE_NAME);
File nodesFile = new File(path, NODES_FILE_NAME);
File usersFile = new File(path, USERS_FILE_NAME);
@@ -75,14 +72,27 @@ public class ImportComponent {
List nodes = objectMapper.readValue(file, objectMapper.getTypeFactory().constructCollectionType(List.class,NodeDefinition.class));
for (NodeDefinition node: nodes)
- nodeRepository.save(node);
+ nodeRepository.findById(node.getName()).ifPresentOrElse(
+ existingNode -> {
+ logger.debug("Node {} already present in the database, skipping import", node.getName());
+ },
+ () -> {
+ logger.debug("Node {} not found, saving new node", node.getName());
+ nodeRepository.save(node);
+ }
+ );
} catch (Exception e) {
logger.error("Error loading nodes: {}", e.getMessage(),e);
}
}
private void loadFlowsAndSave(File file) {
- ObjectMapper objectMapper = new ObjectMapper();
+ if (flowRepository.count()>0){
+ logger.info("Flows already present in the database, skipping import");
+ return;
+ }
+
+ ObjectMapper objectMapper = new ObjectMapper();
try{
@@ -96,14 +106,25 @@ public class ImportComponent {
}
private void insertUser(File file) {
+
ObjectMapper objectMapper = new ObjectMapper();
try{
List users = objectMapper.readValue(file, objectMapper.getTypeFactory().constructCollectionType(List.class,LoginEntity.class));
for (LoginEntity user: users){
- user.setPassword(PasswordHasher.hashPassword(user.getPassword()));
- authRepository.save(user);
+ authRepository.findById(user.getUsername()).ifPresentOrElse(
+ existingUser -> {
+ logger.debug("User {} already present in the database, updating password", user.getUsername());
+ existingUser.setPassword(PasswordHasher.hashPassword(user.getPassword()));
+ authRepository.save(existingUser);
+ },
+ () -> {
+ logger.debug("User {} not found, saving new user", user.getUsername());
+ user.setPassword(PasswordHasher.hashPassword(user.getPassword()));
+ authRepository.save(user);
+ });
+
}
} catch (Exception e) {
logger.error("Error loading users: {}", e.getMessage(),e);
diff --git a/src/main/java/it/cnr/isti/workflow/manager/services/TransformerService.java b/src/main/java/it/cnr/isti/workflow/manager/services/TransformerService.java
index b90a707..010e2cf 100644
--- a/src/main/java/it/cnr/isti/workflow/manager/services/TransformerService.java
+++ b/src/main/java/it/cnr/isti/workflow/manager/services/TransformerService.java
@@ -18,8 +18,11 @@ import it.cnr.isti.workflow.manager.model.flows.Flow;
import it.cnr.isti.workflow.manager.model.flows.IOModel;
import it.cnr.isti.workflow.manager.model.flows.Node;
import it.cnr.isti.workflow.manager.model.flows.errors.FlowError;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.UserNodeDefinition;
import it.cnr.isti.workflow.manager.repositories.NodeDefinitionRepository;
+import it.cnr.isti.workflow.manager.repositories.UserNodeDefinitionRepository;
+
import static it.cnr.isti.workflow.manager.model.flows.errors.FlowError.error;
import static it.cnr.isti.workflow.manager.model.flows.errors.ErrorType.*;
@@ -34,6 +37,10 @@ public class TransformerService {
@Autowired
NodeDefinitionRepository nodeDefinitionRepository;
+ @Autowired
+ UserNodeDefinitionRepository userNodeDefinitionRepository;
+
+
public ExecutionObject transform(Flow flow) {
Map steps = new HashMap<>();
@@ -82,7 +89,7 @@ public class TransformerService {
private ExecutionStep getStep(Node node, ExecutionContext context) {
// prende l'executor per il tipo di nodo
- NodeDefinition nodeDefinition = nodeDefinitionRepository.findById(node.getType())
+ UserNodeDefinition nodeDefinition = userNodeDefinitionRepository.findById(node.getType())
.orElseThrow(() -> new RuntimeException("Node definition not found for node type: " + node.getType()));
if (!executors.containsKey(nodeDefinition.getExecutor()))
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 4ec7eee..2b603c1 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -6,7 +6,7 @@ spring.datasource.username=${DB_USER:lucio}
spring.datasource.password=${DB_PASSWORD:password}
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
-spring.jpa.hibernate.ddl-auto=update
+spring.jpa.hibernate.ddl-auto=create-drop
# Keycloak
#keycloak.realm=${REALM_NAME:wf-editor}
@@ -25,7 +25,9 @@ spring.jpa.hibernate.ddl-auto=update
# create and drop table, good for testing, production set to none or comment it
-app.db.init.enabled=false
+app.db.init.enabled=true
+
+
app.security.key=${WFEDITOR_SECRET_KEY:088c65fd2a5ca418a79cd10df5dff15c0a79781c0da4fd43c1c14e4e2d7af1ff}
app.ollama.internal.key=${OLLAMA_INTERNAL_KEY:ollama}
app.ollama.internal.url=${OLLAMA_INTERNAL_URL:https://ollama.internal/api}
diff --git a/src/main/resources/workflow-editor-init/nodes.json b/src/main/resources/workflow-editor-init/nodes.json
index 13f0033..95b8d6d 100644
--- a/src/main/resources/workflow-editor-init/nodes.json
+++ b/src/main/resources/workflow-editor-init/nodes.json
@@ -1,6 +1,6 @@
[
- {
- "type": "Requirement Generator",
+ {
+ "name": "Requirement Generator",
"category": "Generators",
"executor": "GENERIC-AI",
"color": "black",
@@ -39,7 +39,7 @@
}
},
{
- "type": "Requirements Analyzer",
+ "name": "Requirements Analyzer",
"category": "Analyzers",
"executor": "GENERIC-AI",
"color": "black",
@@ -78,7 +78,7 @@
}
},
{
- "type": "Requirements Corrector",
+ "name": "Requirements Corrector",
"category": "Correctors",
"executor": "GENERIC-AI",
"color": "black",
@@ -117,7 +117,7 @@
}
},
{
- "type": "Class Modeller (UML)",
+ "name": "Class Modeller (UML)",
"category": "Modellers",
"executor": "GENERIC-AI",
"color": "black",
@@ -157,7 +157,7 @@
}
},
{
- "type": "InputDispatcher",
+ "name": "InputDispatcher",
"category": "Dispachers",
"executor": "NoOp",
"color": "black",
@@ -179,7 +179,7 @@
"inputTranslators": { }
},
{
- "type": "Sequence Modeler",
+ "name": "Sequence Modeler",
"category": "Modellers",
"executor": "GENERIC-AI",
"color": "black",
@@ -220,7 +220,7 @@
}
},
{
- "type": "Code Generator",
+ "name": "Code Generator",
"category": "Generators",
"executor": "GENERIC-AI",
"color": "black",
diff --git a/src/test/java/it/cnr/isti/workflow/manager/FlowTest.java b/src/test/java/it/cnr/isti/workflow/manager/FlowTest.java
index 1067102..bfc1535 100644
--- a/src/test/java/it/cnr/isti/workflow/manager/FlowTest.java
+++ b/src/test/java/it/cnr/isti/workflow/manager/FlowTest.java
@@ -118,7 +118,7 @@ public class FlowTest {
flowRepository.save(flow);
}
- @Test
+ //@Test
void transform() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Flow flow = objectMapper.readValue(FLOW, Flow.class);
diff --git a/src/test/java/it/cnr/isti/workflow/manager/executors/GenericAIExecutorTest.java b/src/test/java/it/cnr/isti/workflow/manager/executors/GenericAIExecutorTest.java
index bd2a8df..3228455 100644
--- a/src/test/java/it/cnr/isti/workflow/manager/executors/GenericAIExecutorTest.java
+++ b/src/test/java/it/cnr/isti/workflow/manager/executors/GenericAIExecutorTest.java
@@ -26,6 +26,6 @@ public class GenericAIExecutorTest {
@Test
public void testGetAvaiableAIModels() {
assertTrue(genericAIExecutor.getAvaiableAIModels().size()>0);
- assertEquals(genericAIExecutor.getAvaiableAIModels().keySet().stream().findFirst().orElse(""), "google-gemini");
+ //assertEquals(genericAIExecutor.getAvaiableAIModels().keySet().stream().findFirst().orElse(""), "google-gemini");
}
}
diff --git a/src/test/java/it/cnr/isti/workflow/manager/repositories/NodeDefRepoTest.java b/src/test/java/it/cnr/isti/workflow/manager/repositories/NodeDefRepoTest.java
index 31a043c..29984d6 100644
--- a/src/test/java/it/cnr/isti/workflow/manager/repositories/NodeDefRepoTest.java
+++ b/src/test/java/it/cnr/isti/workflow/manager/repositories/NodeDefRepoTest.java
@@ -7,15 +7,18 @@ import org.springframework.test.context.TestPropertySource;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.cnr.isti.workflow.manager.model.types.IOType;
-import it.cnr.isti.workflow.manager.model.types.NodeDefinition;
import it.cnr.isti.workflow.manager.model.types.ParameterDefinition;
import it.cnr.isti.workflow.manager.model.types.ParameterType;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.InputNodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.NodeDefinition;
+import it.cnr.isti.workflow.manager.model.types.nodes.definitions.UserNodeDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import static org.junit.jupiter.api.Assertions.*;
import java.io.StringWriter;
+import java.util.Map;
import java.util.stream.StreamSupport;
@SpringBootTest
@@ -26,7 +29,7 @@ class NodeDefRepoTest {
private static final String NODE_EXAMPLE_JSON = """
{
- "type": "Translator",
+ "name": "Translator",
"category": "TRANSLATOR",
"color": "black",
"createdBy": "lucio.lelii",
@@ -79,15 +82,19 @@ class NodeDefRepoTest {
@Autowired
private NodeDefinitionRepository nodeRepository;
+ @Autowired
+ private InputDefinitionRepository inputNodeRepository;
+
+
@Test
void testStoreAndFindNode() {
- NodeDefinition node = NodeDefinition.builder().type("DefectDetection")
+ NodeDefinition node = UserNodeDefinition.builder().name("DefectDetection")
.executor("GENERIC-AI").category("DefectDetection").createdBy("lucio.lelii").input("file", IOType.Csv)
- .fixedParameter("LLM",
- ParameterDefinition.builder().name("param").label("param").type(ParameterType.Text).build())
+ .fixedParameters(Map.of("LLM",
+ ParameterDefinition.builder().name("param").label("param").type(ParameterType.Text).build()))
.output("file", IOType.Csv).build();
nodeRepository.save(node);
- NodeDefinition foundNode = nodeRepository.findById(node.getType()).orElse(null);
+ NodeDefinition foundNode = nodeRepository.findById(node.getName()).orElse(null);
assertNotNull(foundNode);
assertFalse(foundNode.getFixedParameters().isEmpty());
assertTrue(foundNode.getRuntimeParameters().isEmpty());
@@ -95,25 +102,33 @@ class NodeDefRepoTest {
@Test
void testStoreAndFindAll() {
- NodeDefinition node = NodeDefinition.builder().type("DefectDetection")
+ NodeDefinition node = UserNodeDefinition.builder().name("DefectDetection")
.executor("GENERIC-AI").category("DefectDetection").createdBy("lucio.lelii").input("file", IOType.Csv).output("file", IOType.Csv)
.build();
nodeRepository.save(node);
NodeDefinition returnNode = StreamSupport.stream(nodeRepository.findAll().spliterator(), false)
- .filter(n -> n.getType().equals(node.getType())).findFirst().orElse(null);
+ .filter(n -> n.getName().equals(node.getName())).findFirst().orElse(null);
assertNotNull(returnNode);
}
+ @Test
+ void getSystemNodeDefinitions() {
+ Iterable nodes = inputNodeRepository.findAll();
+ assertNotNull(nodes);
+ long count = StreamSupport.stream(nodes.spliterator(), false).count();
+ //assertTrue(count == IOType.values().length);
+ }
+
@Test
void testStoreAndSerializeAsJson() throws Exception {
ObjectMapper mapper = new ObjectMapper();
- NodeDefinition node = NodeDefinition.builder().type("DefectDetection")
+ NodeDefinition node = UserNodeDefinition.builder().name("DefectDetection")
.executor("GENERIC-AI").category("DefectDetection").createdBy("lucio.lelii").input("file", IOType.Csv)
- .fixedParameter("LLM",
- ParameterDefinition.builder().name("param").label("param").type(ParameterType.Text).build())
+ .fixedParameters(Map.of("LLM",
+ ParameterDefinition.builder().name("param").label("param").type(ParameterType.Text).build()))
.output("file", IOType.Csv).build();
nodeRepository.save(node);
- NodeDefinition foundNode = nodeRepository.findById(node.getType()).orElse(null);
+ NodeDefinition foundNode = nodeRepository.findById(node.getName()).orElse(null);
assertNotNull(foundNode);
foundNode.getInputs().forEach((k, v) -> logger.info("input: {} {}", k, v));
StringWriter sw = new StringWriter();
@@ -126,9 +141,9 @@ class NodeDefRepoTest {
public void nodeTypeDeserialization(){
ObjectMapper mapper = new ObjectMapper();
try {
- NodeDefinition node = mapper.readValue(NODE_EXAMPLE_JSON, NodeDefinition.class);
+ UserNodeDefinition node = mapper.readValue(NODE_EXAMPLE_JSON, UserNodeDefinition.class);
assertNotNull(node);
- assertEquals("Translator", node.getType());
+ assertEquals("Translator", node.getName());
assertEquals("TRANSLATOR", node.getCategory());
assertEquals("Generic AI Executor", node.getExecutor());
assertNotNull(node.getInputs());
@@ -141,4 +156,19 @@ class NodeDefRepoTest {
}
}
+ @Test
+ public void serializationTest(){
+ NodeDefinition node = UserNodeDefinition.builder().name("DefectDetection")
+ .executor("GENERIC-AI").category("DefectDetection").createdBy("lucio.lelii").input("file", IOType.Csv).output("file", IOType.Csv)
+ .build();
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ String json = mapper.writeValueAsString(node);
+ assertNotNull(json);
+ logger.info("Serialized NodeDefinition: {}", json);
+ } catch (Exception e) {
+ fail("Serialization failed: " + e.getMessage());
+ }
+ }
+
}