From 9b8df2effc8b7a582ecef8a45517d045894bd582 Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 8 Dec 2024 13:29:19 +0100 Subject: [PATCH 001/148] init --- .idea/dataSources.xml | 17 + use-api/pom.xml | 142 ++++++++ .../main/java/org/tzi/use/MClassFacade.java | 31 ++ .../main/java/org/tzi/use/OpenApiConfig.java | 29 ++ .../java/org/tzi/use/UseAPIApplication.java | 29 ++ .../use/graphql/services/MClassGService.java | 36 ++ .../java/org/tzi/use/model/Attribute.java | 57 +++ .../java/org/tzi/use/model/Operation.java | 60 ++++ .../main/java/org/tzi/use/model/UseClass.java | 74 ++++ .../org/tzi/use/repository/AttributeRepo.java | 7 + .../org/tzi/use/repository/ClassRepo.java | 8 + .../org/tzi/use/repository/OperationRepo.java | 8 + .../rest/controller/RestApiController.java | 43 +++ .../tzi/use/rest/services/MClassRService.java | 27 ++ .../src/main/resources/application.properties | 19 + use-api/src/main/resources/docker-compose.yml | 28 ++ .../main/resources/graphql/schema.graphqls | 42 +++ .../use-webapi.postman_collection.json | 249 +++++++++++++ .../org/tzi/use/RestApiControllerTest.java | 148 ++++++++ use-api/target/classes/application.properties | 19 + use-api/target/classes/docker-compose.yml | 28 ++ .../target/classes/graphql/schema.graphqls | 42 +++ .../classes/org/tzi/use/MClassFacade.class | Bin 0 -> 1900 bytes .../classes/org/tzi/use/OpenApiConfig.class | Bin 0 -> 955 bytes .../org/tzi/use/UseAPIApplication.class | Bin 0 -> 2380 bytes .../services/MClassGService$MClassInput.class | Bin 0 -> 2411 bytes .../use/graphql/services/MClassGService.class | Bin 0 -> 1855 bytes .../classes/org/tzi/use/model/Attribute.class | Bin 0 -> 1257 bytes .../classes/org/tzi/use/model/Operation.class | Bin 0 -> 1273 bytes .../classes/org/tzi/use/model/UseClass.class | Bin 0 -> 2379 bytes .../org/tzi/use/repository/ClassRepo.class | Bin 0 -> 339 bytes .../rest/controller/RestApiController.class | Bin 0 -> 2395 bytes .../use/rest/services/MClassRService.class | Bin 0 -> 1237 bytes .../use-webapi.postman_collection.json | 249 +++++++++++++ .../compile/default-compile/createdFiles.lst | 0 .../compile/default-compile/inputFiles.lst | 12 + .../default-testCompile/createdFiles.lst | 1 + .../default-testCompile/inputFiles.lst | 1 + .../2024-10-18T01-08-48_582.dumpstream | 5 + .../2024-10-18T01-16-43_107.dumpstream | 5 + .../2024-10-18T01-17-10_802.dumpstream | 5 + .../2024-10-18T08-54-51_699.dumpstream | 5 + .../2024-10-18T09-06-30_147.dumpstream | 5 + .../2024-10-18T09-07-35_821.dumpstream | 5 + .../org/tzi/use/RestApiControllerTest.class | Bin 0 -> 312 bytes .../org/tzi/use/util/AbstractBagTest.java | 307 +++++++++++++++++ .../test/java/org/tzi/use/util/AllTests.java | 44 +++ .../org/tzi/use/util/CombinationTest.java | 74 ++++ .../java/org/tzi/use/util/ReportTest.java | 70 ++++ .../java/org/tzi/use/util/StringUtilTest.java | 62 ++++ .../java/org/tzi/use/util/soil/AllTests.java | 55 +++ .../tzi/use/util/soil/StateChangesTest.java | 307 +++++++++++++++++ .../tzi/use/util/soil/SymbolTableTest.java | 130 +++++++ .../util/soil/VariableEnvironmentTest.java | 326 ++++++++++++++++++ .../tzi/use/util/soil/VariableSetTest.java | 243 +++++++++++++ .../src/it/java/org/tzi/use/main/ShellIT.java | 304 ++++++++++++++++ .../src/main/java/org/tzi/use/main/Main.java | 259 ++++++++++++++ .../org/tzi/use/util/input/ShellReadline.java | 71 ++++ use-gui/src/main/resources/images/use1.gif | Bin 0 -> 1706 bytes .../org/tzi/use/util/DiagramUtilTest.java | 130 +++++++ 60 files changed, 3818 insertions(+) create mode 100644 .idea/dataSources.xml create mode 100644 use-api/pom.xml create mode 100644 use-api/src/main/java/org/tzi/use/MClassFacade.java create mode 100644 use-api/src/main/java/org/tzi/use/OpenApiConfig.java create mode 100644 use-api/src/main/java/org/tzi/use/UseAPIApplication.java create mode 100644 use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java create mode 100644 use-api/src/main/java/org/tzi/use/model/Attribute.java create mode 100644 use-api/src/main/java/org/tzi/use/model/Operation.java create mode 100644 use-api/src/main/java/org/tzi/use/model/UseClass.java create mode 100644 use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java create mode 100644 use-api/src/main/java/org/tzi/use/repository/ClassRepo.java create mode 100644 use-api/src/main/java/org/tzi/use/repository/OperationRepo.java create mode 100644 use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java create mode 100644 use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java create mode 100644 use-api/src/main/resources/application.properties create mode 100644 use-api/src/main/resources/docker-compose.yml create mode 100644 use-api/src/main/resources/graphql/schema.graphqls create mode 100644 use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json create mode 100644 use-api/src/test/java/org/tzi/use/RestApiControllerTest.java create mode 100644 use-api/target/classes/application.properties create mode 100644 use-api/target/classes/docker-compose.yml create mode 100644 use-api/target/classes/graphql/schema.graphqls create mode 100644 use-api/target/classes/org/tzi/use/MClassFacade.class create mode 100644 use-api/target/classes/org/tzi/use/OpenApiConfig.class create mode 100644 use-api/target/classes/org/tzi/use/UseAPIApplication.class create mode 100644 use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class create mode 100644 use-api/target/classes/org/tzi/use/graphql/services/MClassGService.class create mode 100644 use-api/target/classes/org/tzi/use/model/Attribute.class create mode 100644 use-api/target/classes/org/tzi/use/model/Operation.class create mode 100644 use-api/target/classes/org/tzi/use/model/UseClass.class create mode 100644 use-api/target/classes/org/tzi/use/repository/ClassRepo.class create mode 100644 use-api/target/classes/org/tzi/use/rest/controller/RestApiController.class create mode 100644 use-api/target/classes/org/tzi/use/rest/services/MClassRService.class create mode 100644 use-api/target/classes/postman_collection/use-webapi.postman_collection.json create mode 100644 use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst create mode 100644 use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst create mode 100644 use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst create mode 100644 use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst create mode 100644 use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream create mode 100644 use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream create mode 100644 use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream create mode 100644 use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream create mode 100644 use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream create mode 100644 use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream create mode 100644 use-api/target/test-classes/org/tzi/use/RestApiControllerTest.class create mode 100644 use-core/src/test/java/org/tzi/use/util/AbstractBagTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/AllTests.java create mode 100644 use-core/src/test/java/org/tzi/use/util/CombinationTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/ReportTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/StringUtilTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/soil/AllTests.java create mode 100644 use-core/src/test/java/org/tzi/use/util/soil/StateChangesTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/soil/SymbolTableTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/soil/VariableEnvironmentTest.java create mode 100644 use-core/src/test/java/org/tzi/use/util/soil/VariableSetTest.java create mode 100644 use-gui/src/it/java/org/tzi/use/main/ShellIT.java create mode 100644 use-gui/src/main/java/org/tzi/use/main/Main.java create mode 100644 use-gui/src/main/java/org/tzi/use/util/input/ShellReadline.java create mode 100644 use-gui/src/main/resources/images/use1.gif create mode 100644 use-gui/src/test/java/org/tzi/use/util/DiagramUtilTest.java diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 000000000..9ef790c41 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,17 @@ + + + + + mongo + true + com.dbschema.MongoJdbcDriver + mongodb://localhost:27017 + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/use-api/pom.xml b/use-api/pom.xml new file mode 100644 index 000000000..1d8d953c4 --- /dev/null +++ b/use-api/pom.xml @@ -0,0 +1,142 @@ + + + + use + org.tzi.use + 7.1.1 + + 4.0.0 + + use-api + + + + 21 + 21 + UTF-8 + + + + + + org.springframework.boot + spring-boot-dependencies + 3.1.5 + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + use + org.tzi.use + 7.1.1 + pom + compile + + + org.springframework.boot + spring-boot-starter-graphql + + + org.springframework.boot + spring-boot-starter-web + + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework + spring-webflux + test + + + org.springframework.graphql + spring-graphql-test + test + + + org.springdoc + springdoc-openapi-ui + 1.7.0 + + + io.rest-assured + rest-assured + 5.5.0 + test + + + + org.junit.jupiter + junit-jupiter-api + 5.8.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.8.2 + test + + + org.tzi.use + use-core + 7.1.1 + compile + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + run-newman-tests + test + + exec + + + newman + + run + ${project.basedir}/src/main/resources/postman_collection/use-webapi.postman_collection.json + --reporters + cli + + + + + + + + \ No newline at end of file diff --git a/use-api/src/main/java/org/tzi/use/MClassFacade.java b/use-api/src/main/java/org/tzi/use/MClassFacade.java new file mode 100644 index 000000000..61c705236 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/MClassFacade.java @@ -0,0 +1,31 @@ +package org.tzi.use; + +import org.tzi.use.api.UseApiException; +import org.tzi.use.api.UseModelApi; +import org.tzi.use.model.Attribute; +import org.tzi.use.model.Operation; +import org.tzi.use.model.UseClass; +import org.tzi.use.uml.mm.MAttribute; +import org.tzi.use.uml.mm.MClass; +import org.tzi.use.uml.mm.MInvalidModelException; +import org.tzi.use.uml.mm.MOperation; + +public class MClassFacade { + + public static UseClass createMClass(UseClass aClass) throws UseApiException, MInvalidModelException { + UseModelApi useModelApi = new UseModelApi(); + MClass mClass; + mClass = useModelApi.createClass(aClass.getName_mclass(), false); + //for each attr add + for (Attribute attribute : aClass.getAttributes()) { + MAttribute tmp_mAttribute = useModelApi.createAttribute(mClass.name(), attribute.getName_attr(), attribute.getType()); + + } + //for each operation add + for (Operation operation : aClass.getOperations()) { + MOperation tmp_mOperation = useModelApi.createOperation(mClass.name(), operation.getHead(), new String[0][0], operation.getBody()); + } + //TODO return the MClass for later to be saved inside the DB + return aClass; + } +} diff --git a/use-api/src/main/java/org/tzi/use/OpenApiConfig.java b/use-api/src/main/java/org/tzi/use/OpenApiConfig.java new file mode 100644 index 000000000..ce8f2cf92 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/OpenApiConfig.java @@ -0,0 +1,29 @@ +package org.tzi.use; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Contact; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.info.License; +import io.swagger.v3.oas.annotations.servers.Server; + +@OpenAPIDefinition( + info = @Info( + title = "USE API", + description = "OpenAPI Dokumentation für die USE API", + contact = @Contact( + name = "Hüseyin Akkiran", + email = "Hueseyin.Akkiran@haw-hamburg.de" + ), + version = "1.0", + license = @License( + name = "GPL-2.0 license", + url = "https://github.com/useocl/use/blob/master/COPYING")), + servers = { + @Server( + description = "Lokale Umgebung", + url = "http://localhost:8080" + ) + } +) +public class OpenApiConfig { +} \ No newline at end of file diff --git a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java new file mode 100644 index 000000000..9d2cb6670 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java @@ -0,0 +1,29 @@ +package org.tzi.use; + +import org.springframework.boot.ApplicationRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.tzi.use.model.Attribute; +import org.tzi.use.model.UseClass; +import org.tzi.use.model.Operation; +import org.tzi.use.repository.ClassRepo; + +@SpringBootApplication +public class UseAPIApplication { + public static void main(String[] args) { + SpringApplication.run(UseAPIApplication.class, args); + } + + @Bean + ApplicationRunner init(ClassRepo classRepo) { + return args -> { + Attribute name = new Attribute("name","String"); + Operation operation = new Operation("operation()"); + + UseClass mclass2 = classRepo.save(new UseClass("TestClass2",name, operation)); + + + }; + } +} diff --git a/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java b/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java new file mode 100644 index 000000000..26d4b843c --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java @@ -0,0 +1,36 @@ +package org.tzi.use.graphql.services; + +import org.springframework.graphql.data.method.annotation.Argument; +import org.springframework.graphql.data.method.annotation.MutationMapping; +import org.springframework.graphql.data.method.annotation.QueryMapping; +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; +import org.tzi.use.model.Attribute; +import org.tzi.use.model.UseClass; +import org.tzi.use.model.Operation; +import org.tzi.use.repository.ClassRepo; + +import java.util.List; + +@Controller +@Service +public class MClassGService { + private final ClassRepo classRepo; + + public MClassGService(ClassRepo repo) { + this.classRepo = repo; + } + + @QueryMapping + public Iterable classes() { + return classRepo.findAll(); + } + + @MutationMapping + public UseClass aClass(@Argument MClassInput mClassInput) { + UseClass tmpUseClass = new UseClass(mClassInput.name_mclass, mClassInput.attributes,mClassInput.operations); + return classRepo.save(tmpUseClass); + } + + private record MClassInput(String name_mclass, List attributes, List operations) {} +} diff --git a/use-api/src/main/java/org/tzi/use/model/Attribute.java b/use-api/src/main/java/org/tzi/use/model/Attribute.java new file mode 100644 index 000000000..687a86920 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/model/Attribute.java @@ -0,0 +1,57 @@ +package org.tzi.use.model; + +import jakarta.persistence.*; +import org.springframework.data.mongodb.core.mapping.Document; + + +@Document + public class Attribute { + @Id + private String name_attr; + private String type; + +// @ManyToOne +// @JoinColumn(name = "name_mclass", nullable = false) +// private UseClass mclass; + + + // Getters and Setters + + public String getName_attr() { + return name_attr; + } + + public void setName_attr(String name_attr) { + this.name_attr = name_attr; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +// public UseClass getMclass() { +// return mclass; +// } +// +// public void setMclass(UseClass mclass) { +// this.mclass = mclass; +// } + + //Constructors + public Attribute(String name_attr, String type){ + this.name_attr = name_attr; + this.type = type; + } + + public Attribute(String name, String string, UseClass mclass) { + this.name_attr = name; + this.type = string; +// this.mclass = mclass; + } + + public Attribute(){} +} diff --git a/use-api/src/main/java/org/tzi/use/model/Operation.java b/use-api/src/main/java/org/tzi/use/model/Operation.java new file mode 100644 index 000000000..59c452701 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/model/Operation.java @@ -0,0 +1,60 @@ +package org.tzi.use.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Operation { + @Id + private String head; + + private String body; + +// @ManyToOne +// @JoinColumn(name = "name_mclass", nullable = false) +// private UseClass mclass; + + + // Getters and Setters + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getHead() { + return head; + } + + public void setHead(String head) { + this.head = head; + } + +// public UseClass getMclass() { +// return mclass; +// } +// +// public void setMclass(UseClass mclass) { +// this.mclass = mclass; +// } + + //Constructors + public Operation(String head, String body) { + this.head = head; + this.body = body; + } + public Operation(String head, UseClass mclass) { + this.head = head; +// this.mclass = mclass; + } + public Operation(String head) { + this.head = head; + } + public Operation() {} + + +} diff --git a/use-api/src/main/java/org/tzi/use/model/UseClass.java b/use-api/src/main/java/org/tzi/use/model/UseClass.java new file mode 100644 index 000000000..27c69d053 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/model/UseClass.java @@ -0,0 +1,74 @@ +package org.tzi.use.model; + +import jakarta.persistence.*; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.ArrayList; +import java.util.List; + +@Document +public class UseClass { + + @Id + private String id; + + private String name_mclass; + // Unidirectional OneToMany relationship + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "mClass_id") // Foreign key column in the Employee table + private List attributes = new ArrayList<>(); + // Unidirectional OneToMany relationship + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "mClass_id") // Foreign key column in the Employee table + private List operations = new ArrayList<>(); + +// @OneToMany(mappedBy = "children", cascade = CascadeType.ALL, fetch = FetchType.LAZY) +// private List parents = new ArrayList<>(); + +// @OneToMany(mappedBy = "associations", cascade = CascadeType.ALL, fetch = FetchType.LAZY) +// private List associations = new ArrayList<>(); + + + // Getters and Setters + + public String getName_mclass() { + return name_mclass; + } + + public void setName_mclass(String name_mclass) { + this.name_mclass = name_mclass; + } + + public List getAttributes() { + return attributes; + } +// +// public void setAttributes(List attributes) { +// this.attributes = attributes; +// } +// + public List getOperations() { + return operations; + } +// +// public void setOperations(List operations) { +// this.operations = operations; +// } + + //Constructors + public UseClass(String name_mclass, List attributes, List operations) { + this.name_mclass = name_mclass; + this.attributes = attributes; + this.operations = operations; + } + public UseClass(String name_mclass, Attribute attributes, Operation operations) { + this.name_mclass = name_mclass; + this.attributes.add(attributes); + this.operations.add(operations); + } + public UseClass(String name_mclass) { + this.name_mclass = name_mclass; + } + public UseClass() {} + +} diff --git a/use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java b/use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java new file mode 100644 index 000000000..237e34ae4 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java @@ -0,0 +1,7 @@ +//package org.tzi.use.repository; +// +//import org.springframework.data.jpa.repository.JpaRepository; +//import org.tzi.use.model.Attribute; +//@Deprecated +//public interface AttributeRepo extends JpaRepository { +//} diff --git a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java new file mode 100644 index 000000000..9e6b08c54 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java @@ -0,0 +1,8 @@ +package org.tzi.use.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.tzi.use.model.UseClass; + +public interface ClassRepo extends MongoRepository { +} diff --git a/use-api/src/main/java/org/tzi/use/repository/OperationRepo.java b/use-api/src/main/java/org/tzi/use/repository/OperationRepo.java new file mode 100644 index 000000000..ae27148ff --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/repository/OperationRepo.java @@ -0,0 +1,8 @@ +//package org.tzi.use.repository; +// +//import org.springframework.data.jpa.repository.JpaRepository; +//import org.tzi.use.model.Operation; +// +//@Deprecated +//public interface OperationRepo extends JpaRepository { +//} diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java new file mode 100644 index 000000000..0d432bc74 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java @@ -0,0 +1,43 @@ +package org.tzi.use.rest.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.tzi.use.api.UseApiException; +import org.tzi.use.model.UseClass; +import org.tzi.use.rest.services.MClassRService; +import org.tzi.use.uml.mm.MInvalidModelException; + +import java.util.List; + +@RestController +//@RequestMapping("/api") guidelines +public class RestApiController { + + @Autowired + private MClassRService mClassService; + + + @GetMapping("/classes") + public ResponseEntity> getMClasses() { + return ResponseEntity.ok(mClassService.getAllMCLass()); + } + + @PostMapping("/class") + public ResponseEntity createMClass(@RequestBody UseClass aUseClass) { + try { + UseClass savedUseClass = mClassService.saveMClass(aUseClass); + return new ResponseEntity<>(savedUseClass, HttpStatus.CREATED); + }catch (MInvalidModelException e) { + // Return a detailed error message for MInvalidModelException + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } catch (UseApiException e) { + // Return a detailed error message for UseApiException + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + catch (Exception e) { + return new ResponseEntity<>(e.getMessage(),HttpStatus.BAD_REQUEST); + } + } +} diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java new file mode 100644 index 000000000..4ca710434 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java @@ -0,0 +1,27 @@ +package org.tzi.use.rest.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.tzi.use.MClassFacade; +import org.tzi.use.api.UseApiException; +import org.tzi.use.model.UseClass; +import org.tzi.use.repository.ClassRepo; +import org.tzi.use.uml.mm.MInvalidModelException; + +import java.util.List; + +@Service +public class MClassRService { + + @Autowired + private ClassRepo classRepository; + + public UseClass saveMClass(UseClass aUseClass) throws MInvalidModelException, UseApiException { + MClassFacade.createMClass(aUseClass); + return classRepository.save(aUseClass); + } + + public List getAllMCLass(){ + return classRepository.findAll(); + } +} \ No newline at end of file diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties new file mode 100644 index 000000000..0cbfab18c --- /dev/null +++ b/use-api/src/main/resources/application.properties @@ -0,0 +1,19 @@ +spring.application.name=usewebapi +spring.jpa.hibernate.ddl-auto=create-drop +spring.graphql.graphiql.enabled=true +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console +spring.main.allow-bean-definition-overriding=true + +# /api-docs endpoint custom path +springdoc.api-docs.path=/docs +springdoc.swagger-ui.operationsSorter=method +springdoc.swagger-ui.filter=true + +# mongoDB connection +spring.data.mongodb.authentication-database=admin +spring.data.mongodb.username=rootuser +spring.data.mongodb.password=rootpass +spring.data.mongodb.database=use-database +spring.data.mongodb.port=27017 +spring.data.mongodb.host=localhost \ No newline at end of file diff --git a/use-api/src/main/resources/docker-compose.yml b/use-api/src/main/resources/docker-compose.yml new file mode 100644 index 000000000..9222b6e7c --- /dev/null +++ b/use-api/src/main/resources/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.8" +services: + mongodb: + image: mongo + container_name: mongodb + ports: + - 27017:27017 + volumes: + - data:/data + environment: + - MONGO_INITDB_ROOT_USERNAME=rootuser + - MONGO_INITDB_ROOT_PASSWORD=rootpass + mongo-express: + image: mongo-express + container_name: mongo-express + restart: always + ports: + - 8081:8081 + environment: + - ME_CONFIG_MONGODB_ADMINUSERNAME=rootuser + - ME_CONFIG_MONGODB_ADMINPASSWORD=rootpass + - ME_CONFIG_MONGODB_SERVER=mongodb +volumes: + data: {} + +networks: + default: + name: mongodb_network \ No newline at end of file diff --git a/use-api/src/main/resources/graphql/schema.graphqls b/use-api/src/main/resources/graphql/schema.graphqls new file mode 100644 index 000000000..35bfc3f81 --- /dev/null +++ b/use-api/src/main/resources/graphql/schema.graphqls @@ -0,0 +1,42 @@ +####Queries +type Query{ + classes: [Class] +} + + +type Class{ + name_mclass: String! + attributes: [Attribute] + operations: [Operation] +} + +type Attribute{ + name_attr: String! + type: String! +} + +type Operation{ + head: String! + body: String +} + +#### Mutations +type Mutation{ + aUseClass(mClassInput: ClassInput): Class +} + +input ClassInput{ + name_mclass: String! + attributes: [AttributeInput] + operations: [OperationInput] +} + +input AttributeInput{ + name_attr: String! + type: String! +} + +input OperationInput{ + head: String! + body: String +} \ No newline at end of file diff --git a/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json b/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json new file mode 100644 index 000000000..246729bbb --- /dev/null +++ b/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json @@ -0,0 +1,249 @@ +{ + "info": { + "_postman_id": "10464710-2286-4379-89c4-f0c29739d9fb", + "name": "use-webapi", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", + "_exporter_id": "38619616" + }, + "item": [ + { + "name": "empty class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {\r", + " pm.response.to.have.status(201);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"MyClass\"\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "normal class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {\r", + " pm.response.to.have.status(201);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"MyClass3443\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"MyAttr232\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"MyAttr44242\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"operation()1223\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "no class name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"A class must be named\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "basic GET", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"Response is an array\", function () {\r", + " pm.expect(pm.response.json()).to.be.an('array');\r", + "});\r", + "\r", + "pm.test(\"Response contains valid UseClass objects\", function () {\r", + " const responseJson = pm.response.json();\r", + " pm.expect(responseJson).to.be.an('array');\r", + " \r", + " if (responseJson.length > 0) {\r", + " responseJson.forEach((useClass) => {\r", + " pm.expect(useClass).to.have.property('name_mclass');\r", + " pm.expect(useClass.attributes).to.be.an('array');\r", + " pm.expect(useClass.operations).to.be.an('array');\r", + " });\r", + " }\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/classes" + }, + "response": [] + }, + { + "name": "basic POST success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "pm.test(\"Response contains the created UseClass object\", function () {\r", + " const responseJson = pm.response.json();\r", + " pm.expect(responseJson).to.be.an('object');\r", + " pm.expect(responseJson).to.have.property('name_mclass');\r", + " pm.expect(responseJson).to.have.property('attributes').that.is.an('array');\r", + " pm.expect(responseJson).to.have.property('operations').that.is.an('array');\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"ExampleClass\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "basic POST fail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Error message is returned for invalid model\", function () {\r", + " const responseText = pm.response.text(); // Fixed variable name\r", + " pm.expect(responseText).to.be.a('string');\r", + " pm.expect(responseText).to.include(\"A class must be named\"); // Updated error message\r", + "});\r", + "// Add a test to check the length of the response data\r", + "pm.test(\"Response data length is greater than 0\", function () {\r", + " const responseData = pm.response.text(); \r", + " pm.expect(responseData.length).to.be.greaterThan(0, \"Response data should not be empty\");\r", + "});\r", + "\r", + "pm.test(\"Response time is within an acceptable range\", function () {\r", + " pm.expect(pm.response.responseTime).to.be.below(1000);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "packages": {}, + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java b/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java new file mode 100644 index 000000000..01afd4708 --- /dev/null +++ b/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java @@ -0,0 +1,148 @@ +package org.tzi.use; + +import io.restassured.RestAssured; +import io.restassured.response.Response; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.*; +import static org.hamcrest.Matchers.*; + +public class RestApiControllerTest { +// +// @BeforeAll +// public static void setup() { +// // Set the base URI for RestAssured +// RestAssured.baseURI = "http://localhost:8080/api"; // Adjust port if necessary +// } +// +// @Test +// public void testCreateMClass() { +// // Create a sample UseClass JSON payload +// String requestBody = "{\n" + +// " \"name_mclass\": \"Class1\",\n" + +// " \"attributes\": [\n" + +// " {\n" + +// " \"name_attr\": \"Attribute1\",\n" + +// " \"type\": \"String\"\n" + +// " }\n" + +// " ],\n" + +// " \"operations\": [\n" + +// " {\n" + +// " \"head\": \"Operation1\",\n" + +// " \"body\": \"Operation details\"\n" + +// " }\n" + +// " ]\n" + +// "}"; +// +// // Send POST request and validate response +// given() +// .contentType("application/json") +// .body(requestBody) +// .when() +// .post("/mclass") +// .then() +// .statusCode(201) // Expect HTTP 201 Created +// .body("name_mclass", equalTo("Class1")) +// .body("attributes.size()", equalTo(1)) +// .body("attributes[0].name_attr", equalTo("Attribute1")) +// .body("operations.size()", equalTo(1)) +// .body("operations[0].head", equalTo("Operation1")); +// } +// +// @Test +// public void testCreateDuplicateMClass() { +// // Create first UseClass with name "SameClass" +// String requestBody = "{\n" + +// " \"name_mclass\": \"SameClass\"\n" + +// "}"; +// +// // Create the first class +// given() +// .contentType("application/json") +// .body(requestBody) +// .when() +// .post("/mclass") +// .then() +// .statusCode(201); // Expect HTTP 201 Created +// +// // Attempt to create another class with the same name +// given() +// .contentType("application/json") +// .body(requestBody) +// .when() +// .post("/mclass") +// .then() +// .statusCode(400); // Expect HTTP 400 Bad Request or appropriate error code +// } +// +// @Test +// public void testCreateMClassWithoutName() { +// // Create UseClass with no name but with attributes and operations +// String requestBody = "{\n" + +// " \"attributes\": [\n" + +// " {\n" + +// " \"name_attr\": \"Attribute1\",\n" + +// " \"type\": \"String\"\n" + +// " }\n" + +// " ],\n" + +// " \"operations\": [\n" + +// " {\n" + +// " \"head\": \"Operation1\",\n" + +// " \"body\": \"Operation details\"\n" + +// " }\n" + +// " ]\n" + +// "}"; +// +// given() +// .contentType("application/json") +// .body(requestBody) +// .when() +// .post("/mclass") +// .then() +// .statusCode(400); // Expect HTTP 400 Bad Request due to missing name_mclass +// } +// +// @Test +// public void testCreateMClassWithEmptyPayload() { +// // Create UseClass with empty payload +// String requestBody = "{}"; +// +// given() +// .contentType("application/json") +// .body(requestBody) +// .when() +// .post("/mclass") +// .then() +// .statusCode(400); // Expect HTTP 400 Bad Request due to empty payload +// } +// +// @Test +// public void testCreateMClassWithInvalidJson() { +// // Create UseClass with invalid JSON structure +// String requestBody = "{\n" + +// " \"name_mclass\": \"Class1\",\n" + +// " \"attributes\": [\n" + +// " {\n" + +// " \"name_attr\": \"Attribute1\",\n" + +// " \"type\": \"String\"\n" + +// " },\n" + +// " ],\n" + // Extra comma here to create invalid JSON +// " \"operations\": [\n" + +// " {\n" + +// " \"head\": \"Operation1\",\n" + +// " \"body\": \"Operation details\"\n" + +// " }\n" + +// " ]\n" + +// "}"; +// +// given() +// .contentType("application/json") +// .body(requestBody) +// .when() +// .post("/mclass") +// .then() +// .statusCode(400); // Expect HTTP 400 Bad Request due to invalid JSON +// } + +} diff --git a/use-api/target/classes/application.properties b/use-api/target/classes/application.properties new file mode 100644 index 000000000..0cbfab18c --- /dev/null +++ b/use-api/target/classes/application.properties @@ -0,0 +1,19 @@ +spring.application.name=usewebapi +spring.jpa.hibernate.ddl-auto=create-drop +spring.graphql.graphiql.enabled=true +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console +spring.main.allow-bean-definition-overriding=true + +# /api-docs endpoint custom path +springdoc.api-docs.path=/docs +springdoc.swagger-ui.operationsSorter=method +springdoc.swagger-ui.filter=true + +# mongoDB connection +spring.data.mongodb.authentication-database=admin +spring.data.mongodb.username=rootuser +spring.data.mongodb.password=rootpass +spring.data.mongodb.database=use-database +spring.data.mongodb.port=27017 +spring.data.mongodb.host=localhost \ No newline at end of file diff --git a/use-api/target/classes/docker-compose.yml b/use-api/target/classes/docker-compose.yml new file mode 100644 index 000000000..9222b6e7c --- /dev/null +++ b/use-api/target/classes/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.8" +services: + mongodb: + image: mongo + container_name: mongodb + ports: + - 27017:27017 + volumes: + - data:/data + environment: + - MONGO_INITDB_ROOT_USERNAME=rootuser + - MONGO_INITDB_ROOT_PASSWORD=rootpass + mongo-express: + image: mongo-express + container_name: mongo-express + restart: always + ports: + - 8081:8081 + environment: + - ME_CONFIG_MONGODB_ADMINUSERNAME=rootuser + - ME_CONFIG_MONGODB_ADMINPASSWORD=rootpass + - ME_CONFIG_MONGODB_SERVER=mongodb +volumes: + data: {} + +networks: + default: + name: mongodb_network \ No newline at end of file diff --git a/use-api/target/classes/graphql/schema.graphqls b/use-api/target/classes/graphql/schema.graphqls new file mode 100644 index 000000000..35bfc3f81 --- /dev/null +++ b/use-api/target/classes/graphql/schema.graphqls @@ -0,0 +1,42 @@ +####Queries +type Query{ + classes: [Class] +} + + +type Class{ + name_mclass: String! + attributes: [Attribute] + operations: [Operation] +} + +type Attribute{ + name_attr: String! + type: String! +} + +type Operation{ + head: String! + body: String +} + +#### Mutations +type Mutation{ + aUseClass(mClassInput: ClassInput): Class +} + +input ClassInput{ + name_mclass: String! + attributes: [AttributeInput] + operations: [OperationInput] +} + +input AttributeInput{ + name_attr: String! + type: String! +} + +input OperationInput{ + head: String! + body: String +} \ No newline at end of file diff --git a/use-api/target/classes/org/tzi/use/MClassFacade.class b/use-api/target/classes/org/tzi/use/MClassFacade.class new file mode 100644 index 0000000000000000000000000000000000000000..8d183f1872b81f0850a9a77d50f966b4593f4012 GIT binary patch literal 1900 zcma)7NpllN6#m+h-L}*QBg`h-F@#O>!k8_K<&YSI!63;AHU@0A)~HJiXe(*tf}B!C z6_vk`Uyy5Z5#>-tapA&=6F-JZk-VPKj5U_1LWiF2_rAA&-B0g6{qq{YJX8cd2yui3 zdeO%)^jL06qbSP-V>$O&nKnb;oK?2$3k;z|a*d;(VWd(k81}E0(Wom!RxRUZU1chH zRh+L{5paYeh(d4-3hcsehIl)^q=DLEp(yKhhFt|^XJtt}D4DKcIFU?mXR%_}ta2fx z-R=>HVJ}0}tSM=G_A`l2^m;Pg98;B1ir>mim~m% zgD~(%vYu5>som7&b!~B6-~>)Ggv*XN*cF$X6i0Fg8*X>~lA@Tz6vwo{DNV$o&vr$} zArc};U`F7y1`CfENe$A9vjXR|f|FwPS(U&X-w1q*?-+KwocMtmZgt_Mlc`Qgcj|n{ z4t=u%DUZJ8s&2nkDc3oE=-Le*5y2dO6!^(2;;NE)j*AS#8ylU8X!Iq4%O3h-CI3v9 zd_~|Ymi&@^?+j1AsN`<3I-_@QgCC5jzs_*5olp0AFG^G9716ms?~Ia6TV<7Plya)J zDsx4W#L^X07T09W(&v^iY(KK-`o{y$rrlwR?t@FQD`l8X1i-;(oeHMEL&-3p@09cC z7{_)SEd}OOz&8rZus4dfhS52;Em|c^wIO4UQEW zCM&iypJZgU)zrx4r>3g5uI59A@piUaQD|cND2^OMvK{0_SSoMIqLp_t_TdbXl}e*# zszpolx~HA4Q+meW2(Hm|*S{VxJ>O|f)5)MOqi^rTOR&Ekb%s{01_qI(Rk#2w<7YYz z;1}E=CuGdxjw9grSKxPEVjw*^(L^NF#88Gd!&^AWke%MbR}6pPByEl{yg_0%JUO+6 z37SFSCJeotY2y5B@1OsDAhYj-X49V8T)^x?DD)QdJ=%DoiA8Pve&R36F9eRur!YBvlnB*A$h^c=u;B3y|KI!`i_W+XYOgi--|34b8_gVk| literal 0 HcmV?d00001 diff --git a/use-api/target/classes/org/tzi/use/OpenApiConfig.class b/use-api/target/classes/org/tzi/use/OpenApiConfig.class new file mode 100644 index 0000000000000000000000000000000000000000..b08c0e1784d02e562e1d4d5c67021edb7f289416 GIT binary patch literal 955 zcma)*&2Q5%6u_U?c7<-xG8iy6Soj(%VsQ(XX&}_9gRN4uRx4COoSe)}y(V@QJDuRa z;)H}IF1ztZA)eD}hy&UZ={fKF7yJ3w?;k$_pb6Cy%t5XQ`9&zeJb}tFn=l$N8Pbk_ z%mYJU{*92ryd{v^toDm=g}{nRLTbJWnrcovV=kLx(Nc0CLIU}gI^qP%o{;a#>xeP+y?q0j_Yz5iBxO`z0MX%g`FA}jMxKiA?S&|xZ#hH5u@^{<2d|-bQbFgDx$blkIy&%;_(KZT9DHvfa zU-4t_ozv{L2`n6O9VB9GYZBPVxVvp|Nk76A^*+{gh`ecjjsg*~!+B#eSNEu06KmgeN-V z&DGr+>X8Vz)abbsj5m!&nDSoN+j{BNobv*?G(m*=(3r8_p)?d`nEGy@Vmn1Dh_Yew zBjwYWX@h6g>U2M~5B3m3^Tcuya4*=ASs?9Y2^PasBNpNA#v%7piSxN^0kD5$r*WvX z+1ajb*We)(@gmrV;EPuQB z9-{9C<}5YfCRV+rVHs{~xC3_^u!8n`8dhOV!+m(5VI7os_BbO30BmZoAfp;O?ET8n+pB~ z|BQaB(iz6jj=#zAxtlcEwo3;mlg*xU&)a>@bI;A+|Gs_$AdjC+^r7FtKoWx(5=gy} zyV9ylr)I5IUZ`pyF!aE7>|jBlKRaDEkPx`!dNnKf#kN|$vYz-VzqXWbHtTj(2Da;% zFfn2vnZzl)CorRp{ibI-wQWx})X%QBV^v%?uu7pa;>i?V%Mqw#i@h=mb?N)LXAw;) z(7|%k#kj~-*9p|iz$&=Twq0v^vQk%(6jbZwT$;O2=?YH^tYyPU2OIKK)AjAZ^s)EGCQY@%sW7j+f6)hkzt- zUBKK>eh`ZDCMI!HN6ZSW#zZ`X?hzz%F^k>WbJOJ!%;1)R*(Bz0Ti|N6s<=iGR$uNa zfg906+Eiu}d$j7PXkTD&1V)RtqgGmtit;uzX9Utkw<_yp>DgNDC(k7KN**NBwxh}mL1D%Ok=Au4v0>f3!ea%0C$wL|Aw$7yEBw%1SRN3}z&3ngj zgOCNxG#3UqdJqqei|m?Oi%L3-b*e5Kl`T1?OPRVOu<;J3BsRs-Lz4Gut%h;}pY0W} z{-+P8&mkm^@`%uxi4C%Ww z|3nX7$EjWBW9e+wl|NN<-JMo57dec_2izgYjaN+-HGlWTcFL1|qf?<1xghKHk{u{w zom|o*Jsfn3t^Z!&`Y}x6wrAi6fy*bGa`Lyaz%@3Zk5>{f0HJSUJ}pWXe+7RBXZ9d| z=Sv^%@Tr%<%j*L^lWhac<3mcrxQmad(a!g1t?d$NW9APGKkfPJOCK0z(o`fyf*v1J z4}5~tw9qkfjG%3eTd!%4-}o9W;cV!hX`6IPpfNtheLCi7txJ8tyVleU>jeFk+Ci?( z?IXRJKAX<$;r#MGCN|TT_HbooW*?KA>8aVdJ>2*c(|!00llKRD)u#y(Fvgu{_&JYR z-e?+$yX~N1a*Dh$?%{K$PZHiSe8J=yoa29xPnH%CkHCw@y<@FqGh*&iP;Dx zC)q+Q8%oDD>rNme$&!xQNK$mUZ%apbL5Tu9tz#ZvFyy6()iP|A>!0bgRXORUGICbO zIebY*+IG<15PO`V`ag`+l+N=y7I1-*&tHYMOHprszQ&Z-&l)dyQ(Bc@7$$a{mS@Y* zCwI+bDXnHw)S-}EbG=srYt0%C@vK*h2yv^N@*}D7F|*cjy0XhK8fSE-?s$AV>@>Ll z+-|t!bg3?yw!3Tlj-nIhsBAlwt-F~3KA|xwwE3*wKe|2Lg)J`IV(%y0r`DC+Cp*E% zgZfx5kHtJlJe^3DlDYDLPK@TW#&A0AQmWoeWXCMIB4$rpf1(&xPA~^KmhFk*FzH}u zvUf!2H~Aw+RdhDHFm9-wKx4Jd1Gy;zso@U8@+S;0jZbfh6&?s714$byE@F^Jm0>Zp zgslFKvHDA7hC!oenx5j!IMyfe02>+}>i7|l7%ueJmLGc3>2Nd7Yhs1QtkE;f@Frav z$J-Y#xfu&?+TNbagQdC4lr$8KS1#f@pHIB z?{UI|Fjwhq#PawWWugcf*;V&*k!9u0Tx2tc3Z3U8|J2=La+<{@(reJ&bdJEFD-ZyQ z%gZPd=o*<+4zAEwDc6icQj6Dg968~W9*ZPC73m*yeE|Fn@YhiA1>8vBRWham${Wjv z`0Bs#aftb&l;mMjVU*ufM{$@D4U8FoL;Fw^V~H9@X;~rTDhX-u^f2IyQJgo)=IlTv z#o?8FOWpEar0y1ON8eT4rSB5eFz&c)zh%4ady-V$_XBCk!@@nR;XWP{w?wh!v5HNq LRt-Ed*TkQ#G*%XXw5! z6-Xcil`1~-qY!syov>?=tfFYwduPr)_s+R@Zr;6r^B;f~)+(65q=S-+eVAf6{FrZZ z&*$O5`)%{F=xK(jWf@An!Z2BHbj#R}vV)3?DqM!8NDVywRC;M5yn*8J)<3?N2(>MH zBJnz_K2MT68=1{e?iu^Oh$DttJMXG!Es;7>JD&A1m}V6Ramc}87hhqTVPTvDgY!s+ z{g&@DOxGK2dz4g5-)qZ6Hyz9}%;!mhs4sl)VIpkIGUo8LgKu0M#XQ5+JaWv@PGu)u z595>stA;!fe+Blilu4F{m2^WZ84j8z(lHmuae|@3H7#zYS|p_YXwC+?;Nm-rjAEg< zmQk2gFoW++#ZEC?u74U}lxEa!bd9!WT%1Lnp_K4#!Eh!|loh`@6fxHiO@`C;@wIDo ziFcLsWjNH9p}3m{n?gO{n?9{fx1%2SyIe_Q4;M>%OOgcV3*2LLr({Z|b*S=IZKL7b zZsl##>zXv9AcQP$$U(?;swjg?p9L)!Vi&ukxk402@28=bf#}La5@{<8Bb`-*p=F(u z*i`tDq7HZxslWH`M4xN!1wwB{eUI3>WMXJdUd8a#4ebjLUZr4Ari_&M0zI{-f9$T75TnUM3@zGv^8?* z;e;e;^{z;CN0`e(z3i@sp-{G9rnRfNF+($9KaFmHu9KO?^fgJ}`_Q2GB3Wy+YxXOP zufP_UUcz}!)&!R5eUPxgEJ`>6Gh)t>HJ71r9v8?WKX}B-=u3^sH~KR9-Jr)YM_Zwf i5^mCa0>4;@A#RcVD?O`rmqrS1(N~4=b0qq0%zpq?{`%Aa literal 0 HcmV?d00001 diff --git a/use-api/target/classes/org/tzi/use/model/Attribute.class b/use-api/target/classes/org/tzi/use/model/Attribute.class new file mode 100644 index 0000000000000000000000000000000000000000..6fa1a0dc2caac62ca517856fd6688eede392b156 GIT binary patch literal 1257 zcma)5?P?Q26g`uqjZI^swW(EGZT)Pcc0@%AkwT~lLTJI(g1=<48RN9s-LN}R^r;jq zf zP!%{gMr^nDwPyt;pPInf4T1d1>Yl)*mxI6>U+VuPD2WmcEUmA>F37PsxlgfHP=mn^#mOE-2}Xi$nYVI4rE8MPktD5!%kaz zVZ>ol{XSjfv(Ov(IcATb6}{_s4*<-d(WT0zkUPQ#O*QUFj7Lki~@=RvwqOFqc7U-h01pQ zmg?AhT@}bk`<_6)>9;-$Oza-XkJ9c)uWj!~f%e)B12bC2n8C;&D%r9yj&cc?%BY|! zaCuO%*E~{ABv5>&JsoWbjMP>R1g^j7d69P2fev-Eqc%Oyk7C+TV1|UpGKi#2Euju0 zbXr7yp_Z^UHFdd9LPYMIQf{54mAnq zcmFd7!y2BjPSu70PL{Ix-9!hOy{6=3QVeLwuSk zVD0<8z){=U455;4chzi2U_CAlyJo8&0_mzxesFBJBxmpXUfXXqZO0Gj4cYB7#eU&C zJy&^A1Gi{_ahfW}hduz8&dA(X;;-}qk^&vVY%oBikCKmP_$L3I`hBvY8mU>Y+5 ztDfJo!k=xc8z{^1nyPJm8>nhq27y4@m5zGsG@@Ou_EbKXR$IC)>mc-Pw^i0)XEK<@ zoWPt6`LNy%6+IUt+iqyLt(qN##xj#Z)>wKS<;&3a++Yq1SWMw;205Ig+c3g@{i$k% z0yDd|YlnLR$<4x13d;iLjFEw^_`W>W_;XmoVjAahA%)cp)^Jf^erTsnh#;Fyf#uB+ z9Z{5W;gLYX=HZ2hT{pBHbz}#2y{#&)>xB_hf%EixCjC%aq#qDbxeaA~*(?jp9@s5c zhFxC?SYy(6Yptaks`%Oy$ z^TAl`S1R7?+`$OnN>hcWOl8N4ytrajV828Zm% z_gd7-tBGSr^pY1$2Arg9EMA=Xs0dAGKQ8M3y$~_A9b#(4OEDIMDzf}>=R*YEQwLtx zZ>W2=ZnJE^Z?5XgLg1zW4?6mG`_X3u|K$14tfu5k?|5#@Yu2rX=kunNoeoW`yI!N~ zC^sx)gID1KU$QCAmoNi?b?)?hnR7zlwr1vC$z9&8H;m0X_iyueT<5QY-SbDB&w!b)V-L(u42vJQL$C7z8FNsSZPiXoCW;XWqF z%~+81ILP%kf_y@d96s$a`4vf)3Mdv|V!rqnmcD<9l@p|f%e2v3+}00wPLS5hlScVE zQe2nmf0iX*#wvDMT4rW;9HWwFJ0 zd9D-0*W7P$)LHzc$GtR(`wOJD|G--be8`u?vc$GhDFp{`2makpttzh(96m< lh5@kl=7_^!Ia8kdBf;*EG|pNtPy)9}DZ$UC{=0k!_z$H53NQcw literal 0 HcmV?d00001 diff --git a/use-api/target/classes/org/tzi/use/repository/ClassRepo.class b/use-api/target/classes/org/tzi/use/repository/ClassRepo.class new file mode 100644 index 0000000000000000000000000000000000000000..f1861cd2f4f8a95834fbafe99b4f2c2ee92fe940 GIT binary patch literal 339 zcmbtQU1|a`5dNaAt6L~Nf+y%4Af-?WecB?pc!21pA=}-JB-x6-crPD3fQJ&3EsFT+ z!^|)P-`^aLyFGvpJSFHcjEz;~H=0@}$;zd1+8ev3&q_Eq4SRwIhL=+O393Y+XfiM5 z!Y3Fo@Q8Iws~h!WMJ-px{!$^lpxQLb6!UAs?|6!Y{{jr7T&qU-)=GwLb}PWMJILQU z@Htg&3R%(2$u1MWlFEJb&fhshnw!=x4ef!M%IhYuauzBmf9 z{;D+7A)R)nKcN34f1=apWMgCksXz3Cw7YkEd%Mr>-v0g1AAbSJU?+|~^lKQs)V+6XuZP%+A!7rB4^rhiRKQJn; z6L_v|OV21$&NQrSXGLJNp0!QiFG=sfsz`yw{5uBx)}C(^Le*khHx(xK1_o0t)py)d4~45}2EL6f*>*juO@T=fY5yrsEsW%}U^U zM~2xsU}TzsduVyGni3dL=m?DGEk{0W*2~h{Hff#}oOdgxy=!`wlG}>|!3&G`8C^y5 zpDoF2Mihc!QAwU(B7_%~OLzJ6Y^-F}9F~tqul9OBxq7AnSG$}(Q_Sg9nm64&*Q-NW zHp-S$jY7D=aLh(SrCwl=<wNmFwsbiyT`N}>)YM0L5{{ulgtI=mrWp1VC z%x$@TBy~frlnKmqx7U`b-sC`fU47R3Ek*fLlap!9tsc?4c*$*g75T_gjWzYo$hxDt z{-Q2EulkgQ(}|bj13b(L3vgDbkx9BjX^8Y5X+J6FF8^OqGDrpK;NlyIU&-|0KL2VP zn84TkD+5%(1Efd=R`HNV)ZrCMYHwumH)zKg{T-KIQH+|n8Zj}_Hjxf>z6re=qk(Vv zW%eL^tdYxN9Rs2Hx1{~l%_;Ls$GBGb6O%vOdW}!sVD?o@I7Z?%ZbjuU&d7J$a%hS( zmk&8Od*>LsqAOVDj*5APuz?SE4Aa!Qfhn%cVV3%H)LI~Ti7=Qn(TNe293C;$DU4$S zkIBu4+!J#5Lhd_qbiN(5;=bnzfjn2o(7&T$ep7?NZy7B}3LQwEb|Bfr7WFj+^fNMj OD2D%1sH)Pm4g3q%yraGV literal 0 HcmV?d00001 diff --git a/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class b/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class new file mode 100644 index 0000000000000000000000000000000000000000..4ffd776f2c0dae023ff486d51df4a1a55f9256ed GIT binary patch literal 1237 zcmaJ>T~8B16g^W)*OpZf1OZV#{A!Cbs5}@;NE#xEvDE|=pQqcQ4sLgwo!KJ(Dosoj zAB@lbDC3>&2Q4TMox6AD-gECgbEd!l{P+o=jEx*p7;%txF^UYs#Gz;l?u($oU)K($ zXBaY@Do|#NVI*JJ&*2iX4stHW;4;jHQG=ULipN^=>b5Vm-VvUtO9t1Aq%g9x$?z;+ z8H{a)b?NiBS|&NA!bOK!T*0`52^Uu}$&eq!iKI4M%c!k9sk ze*N4HY+lstmTh-0j3ZC(C`;Z{XWpJV*Q_u|&Hub6ZDb@vbKH`=E9MfG=^3Qx(K1@; zA&^}pFGF^T>kNX@v0saEk%R9ON literal 0 HcmV?d00001 diff --git a/use-api/target/classes/postman_collection/use-webapi.postman_collection.json b/use-api/target/classes/postman_collection/use-webapi.postman_collection.json new file mode 100644 index 000000000..246729bbb --- /dev/null +++ b/use-api/target/classes/postman_collection/use-webapi.postman_collection.json @@ -0,0 +1,249 @@ +{ + "info": { + "_postman_id": "10464710-2286-4379-89c4-f0c29739d9fb", + "name": "use-webapi", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", + "_exporter_id": "38619616" + }, + "item": [ + { + "name": "empty class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {\r", + " pm.response.to.have.status(201);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"MyClass\"\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "normal class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {\r", + " pm.response.to.have.status(201);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"MyClass3443\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"MyAttr232\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"MyAttr44242\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"operation()1223\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "no class name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"A class must be named\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "basic GET", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"Response is an array\", function () {\r", + " pm.expect(pm.response.json()).to.be.an('array');\r", + "});\r", + "\r", + "pm.test(\"Response contains valid UseClass objects\", function () {\r", + " const responseJson = pm.response.json();\r", + " pm.expect(responseJson).to.be.an('array');\r", + " \r", + " if (responseJson.length > 0) {\r", + " responseJson.forEach((useClass) => {\r", + " pm.expect(useClass).to.have.property('name_mclass');\r", + " pm.expect(useClass.attributes).to.be.an('array');\r", + " pm.expect(useClass.operations).to.be.an('array');\r", + " });\r", + " }\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/classes" + }, + "response": [] + }, + { + "name": "basic POST success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {\r", + " pm.response.to.have.status(201);\r", + "});\r", + "\r", + "pm.test(\"Response contains the created UseClass object\", function () {\r", + " const responseJson = pm.response.json();\r", + " pm.expect(responseJson).to.be.an('object');\r", + " pm.expect(responseJson).to.have.property('name_mclass');\r", + " pm.expect(responseJson).to.have.property('attributes').that.is.an('array');\r", + " pm.expect(responseJson).to.have.property('operations').that.is.an('array');\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name_mclass\": \"ExampleClass\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "basic POST fail", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Error message is returned for invalid model\", function () {\r", + " const responseText = pm.response.text(); // Fixed variable name\r", + " pm.expect(responseText).to.be.a('string');\r", + " pm.expect(responseText).to.include(\"A class must be named\"); // Updated error message\r", + "});\r", + "// Add a test to check the length of the response data\r", + "pm.test(\"Response data length is greater than 0\", function () {\r", + " const responseData = pm.response.text(); \r", + " pm.expect(responseData.length).to.be.greaterThan(0, \"Response data should not be empty\");\r", + "});\r", + "\r", + "pm.test(\"Response time is within an acceptable range\", function () {\r", + " pm.expect(pm.response.responseTime).to.be.below(1000);\r", + "});\r", + "\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "packages": {}, + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 000000000..e69de29bb diff --git a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 000000000..5cab6737d --- /dev/null +++ b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,12 @@ +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\graphql\services\MClassGService.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\repository\AttributeRepo.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\repository\ClassRepo.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\UseAPIApplication.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\repository\OperationRepo.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\MClassFacade.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\model\Operation.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\rest\controller\RestApiController.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\rest\services\MClassRService.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\model\UseClass.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\model\Attribute.java +D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\OpenApiConfig.java diff --git a/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst new file mode 100644 index 000000000..37c3a61e1 --- /dev/null +++ b/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -0,0 +1 @@ +org\tzi\use\RestApiControllerTest.class diff --git a/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 000000000..57b820809 --- /dev/null +++ b/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst @@ -0,0 +1 @@ +D:\Programming\use_web_api\use\use-api\src\test\java\org\tzi\use\RestApiControllerTest.java diff --git a/use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream b/use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream new file mode 100644 index 000000000..0a71e38bc --- /dev/null +++ b/use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-10-18T01:08:48.748 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream b/use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream new file mode 100644 index 000000000..693429e22 --- /dev/null +++ b/use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-10-18T01:16:43.301 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream b/use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream new file mode 100644 index 000000000..b4de26efd --- /dev/null +++ b/use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-10-18T01:17:11.008 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream b/use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream new file mode 100644 index 000000000..c6f4b5187 --- /dev/null +++ b/use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-10-18T08:54:51.858 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream b/use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream new file mode 100644 index 000000000..a802f26be --- /dev/null +++ b/use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-10-18T09:06:30.347 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream b/use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream new file mode 100644 index 000000000..f3382bc0f --- /dev/null +++ b/use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-10-18T09:07:35.994 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/test-classes/org/tzi/use/RestApiControllerTest.class b/use-api/target/test-classes/org/tzi/use/RestApiControllerTest.class new file mode 100644 index 0000000000000000000000000000000000000000..aa928655fb58d279c790e89fe6f727c159e416d7 GIT binary patch literal 312 zcmaiv!AiqG5QhIrlg6gi6py`?Uets804+i(^b{=A()%VZb;~weHX9GVl_$Z25737a zXNyO{8TfbpZ(x@H^!@n-V2)vi2%Qx1013K;;atr|Z+>V>Vnv&Ja5VL*r%_E{0~Lf7iCJ(SF4X_#CWwvuKmoeusN z#{NY&gh}!5org.tzi.use.util. + * + * @author Hanna Bauerdick + * @author Fabian Gutsche + */ +public class AllTests { + + private AllTests(){} + + public static Test suite() { + final TestSuite test = new TestSuite( "All util tests" ); + test.addTestSuite( org.tzi.use.util.AbstractBagTest.class ); + test.addTestSuite( org.tzi.use.util.ReportTest.class ); + test.addTestSuite( org.tzi.use.util.StringUtilTest.class ); + test.addTestSuite( org.tzi.use.util.CombinationTest.class ); + test.addTest(org.tzi.use.util.soil.AllTests.suite()); + return test; + } +} diff --git a/use-core/src/test/java/org/tzi/use/util/CombinationTest.java b/use-core/src/test/java/org/tzi/use/util/CombinationTest.java new file mode 100644 index 000000000..598176a75 --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/CombinationTest.java @@ -0,0 +1,74 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2004 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// $Id: AbstractBagTest.java 2409 2011-07-27 09:45:00Z lhamann $ + +package org.tzi.use.util; + +import java.util.ArrayList; +import java.util.List; + +import org.tzi.use.util.collections.CollectionUtil; +import org.tzi.use.util.collections.MinCombinationsIterator; +import org.tzi.use.util.collections.CollectionUtil.UniqueList; + +import junit.framework.TestCase; + + +/** + * Test comparing Bags with each other. + * + * @author Fabian Gutsche + */ +public class CombinationTest extends TestCase { + + private List getList(int offSet, int numElements) { + List result = new ArrayList(numElements); + for (int index = 1; index <= numElements; ++index) { + result.add(new String(new char[]{(char)(index + offSet + 64)})); + } + return result; + } + + public void testCombination() { + List l1 = getList(0, 3); + List l2 = getList(3, 3); + + List>> result = CollectionUtil.combinationsOne(l1, l2, UniqueList.SECOND_IS_UNIQUE); + assertEquals(64, result.size()); + } + + + public void testCombinationIterator() { + List l1 = getList(0,3); + List l2 = getList(3,3); + + List>> result = CollectionUtil.combinationsOne(l1, l2, UniqueList.SECOND_IS_UNIQUE); + MinCombinationsIterator iter = new MinCombinationsIterator(l1, l2, UniqueList.SECOND_IS_UNIQUE); + + int num = 0; + while(iter.hasNext()) { + List> elem = iter.next(); + assertTrue(result.contains(elem)); + ++num; + } + + assertEquals(result.size(), num); + } +} diff --git a/use-core/src/test/java/org/tzi/use/util/ReportTest.java b/use-core/src/test/java/org/tzi/use/util/ReportTest.java new file mode 100644 index 000000000..a9ce98103 --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/ReportTest.java @@ -0,0 +1,70 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2004 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util; +import java.io.PrintWriter; +import java.io.StringWriter; + +import junit.framework.TestCase; + +/** + * Test Report class. + * + * @author Mark Richters + */ + +public class ReportTest extends TestCase { + + public void test1() { + Report r = new Report(4, "[ $c = $r, $r, $l ]"); + r.addRuler('-'); + r.addRow(); + r.addCell("foo"); + r.addCell(Integer.valueOf(3)); + r.addCell(Double.valueOf(1.2)); + r.addCell(Boolean.FALSE); + + r.addRow(); + r.addCell("foobar"); + r.addCell(Integer.valueOf(453453)); + r.addCell(Double.valueOf(-1.245345345)); + r.addCell(Boolean.TRUE); + + r.addRow(); + r.addCell("line"); + r.addCell(Integer.valueOf(555)); + r.addCell(Double.valueOf(999.0)); + r.addCell(Boolean.TRUE); + r.addRuler('='); + + StringWriter sw1 = new StringWriter(); + PrintWriter p1 = new PrintWriter(sw1); + r.printOn(p1); + p1.flush(); + StringWriter sw2 = new StringWriter(); + PrintWriter p2 = new PrintWriter(sw2); + p2.println("----------------------------------------"); + p2.println("[ foo = 3, 1.2, false ]"); + p2.println("[ foobar = 453453, -1.245345345, true ]"); + p2.println("[ line = 555, 999.0, true ]"); + p2.println("========================================"); + p2.flush(); + assertEquals(sw1.toString(), sw2.toString()); + } +} diff --git a/use-core/src/test/java/org/tzi/use/util/StringUtilTest.java b/use-core/src/test/java/org/tzi/use/util/StringUtilTest.java new file mode 100644 index 000000000..0e3c65a8e --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/StringUtilTest.java @@ -0,0 +1,62 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2004 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util; +import junit.framework.TestCase; + +/** + * Test StringUtil class. + * + * @author Mark Richters + */ + +public class StringUtilTest extends TestCase { + + public StringUtilTest(String name) { + super(name); + } + + public void testNthIndexOf() { + assertEquals(-1, StringUtil.nthIndexOf("abbbb", 0, "bb")); + assertEquals(1, StringUtil.nthIndexOf("abbbb", 1, "bb")); + assertEquals(3, StringUtil.nthIndexOf("abbbb", 2, "bb")); + assertEquals(-1, StringUtil.nthIndexOf("abbbb", 3, "bb")); + assertEquals(7, StringUtil.nthIndexOf("abbbbaabb", 3, "bb")); + assertEquals(-1, StringUtil.nthIndexOf("abbbb", 0, 'b')); + assertEquals(1, StringUtil.nthIndexOf("abbbb", 1, 'b')); + assertEquals(3, StringUtil.nthIndexOf("abbbb", 3, 'b')); + } + + public void testPad() { + assertEquals("a", StringUtil.pad("a", 1)); + assertEquals("a ", StringUtil.pad("a", 2)); + } + + public void testCenter() { + assertEquals(" a ", StringUtil.center("a", 3)); + assertEquals(" a ", StringUtil.center("a", 3)); + } + + public void testEscapeChar() { + assertEquals("a", StringUtil.escapeChar('a', '"')); + assertEquals("\\344", StringUtil.escapeChar('\344', '"')); + assertEquals("\\u1234", StringUtil.escapeChar('\u1234', '"')); + assertEquals("\\t", StringUtil.escapeChar('\t', '"')); + } +} diff --git a/use-core/src/test/java/org/tzi/use/util/soil/AllTests.java b/use-core/src/test/java/org/tzi/use/util/soil/AllTests.java new file mode 100644 index 000000000..695500e62 --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/soil/AllTests.java @@ -0,0 +1,55 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util.soil; + + +import junit.framework.Test; +import junit.framework.TestSuite; + + +/** + * Collection of all soil utility tests + * + * @author Daniel Gent + */ +public class AllTests { + + /** + * no instances required + */ + private AllTests() { + + } + + + /** + * builds the suite of all soil utility tests + * + * @return the suite of all soil utility tests + */ + public static Test suite() { + final TestSuite testSuite = new TestSuite("All soil util tests"); + testSuite.addTestSuite(VariableEnvironmentTest.class); + testSuite.addTestSuite(StateChangesTest.class); + testSuite.addTestSuite(VariableSetTest.class); + testSuite.addTestSuite(SymbolTableTest.class); + return testSuite; + } +} \ No newline at end of file diff --git a/use-core/src/test/java/org/tzi/use/util/soil/StateChangesTest.java b/use-core/src/test/java/org/tzi/use/util/soil/StateChangesTest.java new file mode 100644 index 000000000..7dedab553 --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/soil/StateChangesTest.java @@ -0,0 +1,307 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util.soil; + + +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.junit.Before; +import org.junit.Test; +import org.tzi.use.uml.mm.MAssociation; +import org.tzi.use.uml.mm.MAssociationClass; +import org.tzi.use.uml.mm.MClass; +import org.tzi.use.uml.mm.MModel; +import org.tzi.use.uml.mm.TestModelUtil; +import org.tzi.use.uml.sys.MLink; +import org.tzi.use.uml.sys.MLinkObject; +import org.tzi.use.uml.sys.MObject; +import org.tzi.use.uml.sys.MSystem; +import org.tzi.use.uml.sys.MSystemException; +import org.tzi.use.uml.sys.MSystemState; + + +/** + * Test cases for various methods of {@code StateChanges} + * + * @author Daniel Gent + * @see StateDifference + */ +public class StateChangesTest extends TestCase { + /** the test subject */ + private StateDifference fSC; + /** an arbitrary object */ + private MObject fObject; + /** an arbitrary link */ + private MLink fLink; + /** an arbitrary link object */ + private MLinkObject fLinkObject; + + + /** + * builds the fixture consisting of the {@code StateChanges} object + * + the objects to insert + */ + @Override + @Before + public void setUp() { + + fSC = new StateDifference(); + MModel model = TestModelUtil.getInstance().createComplexModel(); + MClass person = model.getClass("Person"); + MClass company = model.getClass("Company"); + MAssociation isBoss = model.getAssociation("isBoss"); + MAssociationClass job = model.getAssociationClass("Job"); + + MSystem system = new MSystem(model); + MSystemState state = system.state(); + try { + fObject = state.createObject(person, "P"); + MObject c = state.createObject(company, "C"); + fLink = state.createLink(isBoss, Arrays.asList(fObject, fObject), null); + fLinkObject = state.createLinkObject(job, "J", Arrays.asList(fObject, c), null); + } catch (MSystemException e) { + fail(e.getMessage()); + } + } + + + /** + * tests clear, isEmpty + *

+ * - initially the object is empty
+ * - invoking any {@code add} method on an empty {@code StateChanges} + * results in it being not empty anymore
+ * - invoking {@code clear} results in the {@code StateChanges} being + * empty
+ */ + @Test + public void testClearIsEmpty() { + assertTrue(fSC.isEmpty()); + fSC.addNewObject(fObject); + assertFalse(fSC.isEmpty()); + fSC.clear(); + assertTrue(fSC.isEmpty()); + fSC.addModifiedObject(fObject); + assertFalse(fSC.isEmpty()); + fSC.clear(); + assertTrue(fSC.isEmpty()); + fSC.addDeletedObject(fObject); + assertFalse(fSC.isEmpty()); + fSC.clear(); + assertTrue(fSC.isEmpty()); + fSC.addNewLink(fLink); + assertFalse(fSC.isEmpty()); + fSC.clear(); + assertTrue(fSC.isEmpty()); + fSC.addDeletedLink(fLink); + assertFalse(fSC.isEmpty()); + fSC.clear(); + assertTrue(fSC.isEmpty()); + } + + + /** + * tests addNewObject, addModifiedObject, addDeletedObject with a + * non-link-object object + *

+ * - after invoking any one method, the supplied object is either + * in exactly one or in none of the new-, modified- or deleted sets
+ * - two consecutive invocations of different {@code add...Object} methods + * with the same object lead to certain outcomes
+ */ + @Test + public void testAddObject() { + // adding objects to an empty StateChanges object + fSC.addNewObject(fObject); + assertTrue(isOnlyNew(fObject)); + fSC.clear(); + fSC.addModifiedObject(fObject); + assertTrue(isOnlyModified(fObject)); + fSC.clear(); + fSC.addDeletedObject(fObject); + assertTrue(isOnlyDeleted(fObject)); + fSC.clear(); + + // invocations of the add...Object methods in the context of + // previous add...Object calls + + // new, modified = new + fSC.addNewObject(fObject); + fSC.addModifiedObject(fObject); + assertTrue(isOnlyNew(fObject)); + fSC.clear(); + + // new, deleted = empty + fSC.addNewObject(fObject); + fSC.addDeletedObject(fObject); + assertTrue(fSC.isEmpty()); + fSC.clear(); + + // modified, new = new + // hypothetical case, shouldn't be possible to achieve + fSC.addModifiedObject(fObject); + fSC.addNewObject(fObject); + assertTrue(isOnlyNew(fObject)); + fSC.clear(); + + // modified, deleted = deleted + fSC.addModifiedObject(fObject); + fSC.addDeletedObject(fObject); + assertTrue(isOnlyDeleted(fObject)); + fSC.clear(); + + // deleted, new = modified + fSC.addDeletedObject(fObject); + fSC.addNewObject(fObject); + assertTrue(isOnlyModified(fObject)); + fSC.clear(); + + // deleted, modified = modified + // hypothetical case, shouldn't be possible to achieve + fSC.addDeletedObject(fObject); + fSC.addModifiedObject(fObject); + assertTrue(isOnlyModified(fObject)); + fSC.clear(); + } + + + /** + * tests addNewLink, addDeletedLink with a non-link-object link + *

+ * - after invoking one of the methods, the link is either in the set of + * new links or deleted links or in neither of those sets, but not in + * both
+ * - adding a new link which was previously deleted leads to that link + * being in neither the set of new links nor the set of deleted links
+ * - the same holds true for adding a deleted link which was previously + * new
+ */ + @Test + public void testAddLink() { + fSC.addNewLink(fLink); + assertTrue(fSC.getNewLinks().contains(fLink)); + fSC.clear(); + fSC.addDeletedLink(fLink); + assertTrue(fSC.getDeletedLinks().contains(fLink)); + fSC.clear(); + + // new, deleted = empty + fSC.addNewLink(fLink); + fSC.addDeletedLink(fLink); + assertFalse(fSC.getNewLinks().contains(fLink)); + assertFalse(fSC.getDeletedLinks().contains(fLink)); + fSC.clear(); + + // deleted, new = empty + fSC.addDeletedLink(fLink); + fSC.addNewLink(fLink); + assertFalse(fSC.getNewLinks().contains(fLink)); + assertFalse(fSC.getDeletedLinks().contains(fLink)); + fSC.clear(); + } + + + /** + * tests addNew(Link)(Object), addDeleted(Link)(Object) + *

+ * - invoking any of the {@code addNew...} or {@code addDeleted...} methods + * with a link object results in the link object being treated as an + * object and a link, i.E. it doesn't matter which version is used
+ */ + @Test + public void testAddLinkObject() { + fSC.addNewLinkObject(fLinkObject); + assertTrue(fSC.getNewObjects().contains(fLinkObject)); + assertTrue(fSC.getNewLinks().contains(fLinkObject)); + fSC.clear(); + + fSC.addDeletedLinkObject(fLinkObject); + assertTrue(fSC.getDeletedObjects().contains(fLinkObject)); + assertTrue(fSC.getDeletedLinks().contains(fLinkObject)); + fSC.clear(); + + fSC.addNewObject(fLinkObject); + assertTrue(fSC.getNewObjects().contains(fLinkObject)); + assertTrue(fSC.getNewLinks().contains(fLinkObject)); + fSC.clear(); + + fSC.addDeletedObject(fLinkObject); + assertTrue(fSC.getDeletedObjects().contains(fLinkObject)); + assertTrue(fSC.getDeletedLinks().contains(fLinkObject)); + fSC.clear(); + + fSC.addNewLink(fLinkObject); + assertTrue(fSC.getNewObjects().contains(fLinkObject)); + assertTrue(fSC.getNewLinks().contains(fLinkObject)); + fSC.clear(); + + fSC.addDeletedLink(fLinkObject); + assertTrue(fSC.getDeletedObjects().contains(fLinkObject)); + assertTrue(fSC.getDeletedLinks().contains(fLinkObject)); + fSC.clear(); + } + + + /** + * returns true if object is a member of the newObjects set, and not member + * of the other sets + * + * @param object the object to test + * @return true if {@code object} is only in the set of new objects + */ + private boolean isOnlyNew(MObject object) { + return + fSC.getNewObjects().contains(object) + && !fSC.getModifiedObjects().contains(object) + && !fSC.getDeletedObjects().contains(object); + } + + + /** + * returns true if object is a member of the modifiedObjects set, and not + * member of the other sets + * + * @param object the object to test + * @return true if {@code object} is only in the set of modified objects + */ + private boolean isOnlyModified(MObject object) { + return + !fSC.getNewObjects().contains(object) + && fSC.getModifiedObjects().contains(object) + && !fSC.getDeletedObjects().contains(object); + } + + + /** + * returns true if object is a member of the deletedObjects set, and not + * member of the other sets + * + * @param object the object to test + * @return true if {@code object} is only in the set of deleted objects + */ + private boolean isOnlyDeleted(MObject object) { + return + !fSC.getNewObjects().contains(object) + && !fSC.getModifiedObjects().contains(object) + && fSC.getDeletedObjects().contains(object); + } +} diff --git a/use-core/src/test/java/org/tzi/use/util/soil/SymbolTableTest.java b/use-core/src/test/java/org/tzi/use/util/soil/SymbolTableTest.java new file mode 100644 index 000000000..6127a2d98 --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/soil/SymbolTableTest.java @@ -0,0 +1,130 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util.soil; + +import junit.framework.TestCase; + +import org.junit.Before; +import org.junit.Test; +import org.tzi.use.parser.soil.ast.ASTEmptyStatement; +import org.tzi.use.parser.soil.ast.ASTStatement; +import org.tzi.use.uml.ocl.type.Type; +import org.tzi.use.uml.ocl.type.TypeFactory; + + +/** + * Test cases for various methods of {@code SymbolTable}s + * + * @author Daniel Gent + * @see SymbolTable + */ +public class SymbolTableTest extends TestCase { + /** the test subject */ + private SymbolTable fST; + /** arbitrary name */ + private String fVariableName; + /** the ocl Real type */ + private Type fRealType; + /** the ocl Integer type */ + private Type fIntegerType; + /** the ocl String type */ + private Type fStringType; + /** arbitrary statement */ + private ASTStatement fStatement; + + + + /** + * constructs the fixture + */ + @Override + @Before + public void setUp() { + fST = new SymbolTable(); + fVariableName = "name"; + fRealType = TypeFactory.mkReal(); + fIntegerType = TypeFactory.mkInteger(); + fStringType = TypeFactory.mkString(); + fStatement = new ASTEmptyStatement(); + + assertTrue(fIntegerType.conformsTo(fRealType)); + } + + + /** + * tests type setting and getting + * + * @see SymbolTable#getType(String) + * @see SymbolTable#setType(String, Type) + */ + @Test + public void testGetSet() { + assertNull(fST.getType(fVariableName)); + fST.setType(fVariableName, fIntegerType); + assertEquals(fST.getType(fVariableName), fIntegerType); + fST.setType(fVariableName, fRealType); + assertEquals(fST.getType(fVariableName), fRealType); + } + + + /** + * tests state storing and restoring + * + * @see SymbolTable#storeState() + * @see SymbolTable#restoreState(ASTStatement) + */ + @Test + public void testStoreRestore() { + // check if the stack works correctly + fST.setType(fVariableName, fIntegerType); + assertEquals(fST.getType(fVariableName), fIntegerType); + fST.storeState(); + fST.setType(fVariableName, fRealType); + assertEquals(fST.getType(fVariableName), fRealType); + fST.storeState(); + fST.setType(fVariableName, fStringType); + assertEquals(fST.getType(fVariableName), fStringType); + fST.restoreState(fStatement); + assertEquals(fST.getType(fVariableName), fRealType); + fST.restoreState(fStatement); + assertEquals(fST.getType(fVariableName), fIntegerType); + fST.clear(); + + // test dirty-bit + fST.setType(fVariableName, fIntegerType); + fST.storeState(); + fST.setType(fVariableName, fStringType); + fST.restoreState(fStatement); + // the type does not change + assertEquals(fST.getType(fVariableName), fIntegerType); + // but the variable is now dirty + assertTrue(fST.isDirty(fVariableName)); + assertEquals(fST.getCause(fVariableName), fStatement); + fST.clear(); + + fST.setType(fVariableName, fRealType); + fST.storeState(); + fST.setType(fVariableName, fIntegerType); + fST.restoreState(fStatement); + assertEquals(fST.getType(fVariableName), fRealType); + // not dirty, since Integer is a sub-type of Real + assertFalse(fST.isDirty(fVariableName)); + } +} diff --git a/use-core/src/test/java/org/tzi/use/util/soil/VariableEnvironmentTest.java b/use-core/src/test/java/org/tzi/use/util/soil/VariableEnvironmentTest.java new file mode 100644 index 000000000..f98cb91fd --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/soil/VariableEnvironmentTest.java @@ -0,0 +1,326 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util.soil; + + +import junit.framework.TestCase; + +import org.junit.Before; +import org.junit.Test; +import org.tzi.use.TestSystem; +import org.tzi.use.uml.mm.MClass; +import org.tzi.use.uml.mm.MInvalidModelException; +import org.tzi.use.uml.mm.MModel; +import org.tzi.use.uml.mm.ModelFactory; +import org.tzi.use.uml.ocl.value.IntegerValue; +import org.tzi.use.uml.ocl.value.UndefinedValue; +import org.tzi.use.uml.ocl.value.Value; +import org.tzi.use.uml.ocl.value.VarBindings; +import org.tzi.use.uml.sys.MObject; +import org.tzi.use.uml.sys.MSystem; +import org.tzi.use.uml.sys.MSystemException; + + +/** + * Test cases for various methods of {@code VariableEnvironment}s + * + * @author Daniel Gent + * @see VariableEnvironment + */ +public class VariableEnvironmentTest extends TestCase { + private VariableEnvironment ve; + private String n1; + private String n2; + private String n3; + private Value v1; + private Value v2; + private Value v3; + private Value vUnassigned; + + + /** + * constructs fixture + */ + @Override + @Before + public void setUp() throws Exception { + TestSystem testSystem = new TestSystem(); + ve = new VariableEnvironment(testSystem.getState()); + n1 = "n1"; + n2 = "n2"; + n3 = "n3"; + v1 = IntegerValue.valueOf(1); + v2 = IntegerValue.valueOf(2); + v3 = IntegerValue.valueOf(3); + vUnassigned = null; + } + + @Test + public void testIdentity() { + assertEquals(1,1); + } + + /** + * tests clear, isEmpty + *

+ * - empty means one empty frame
+ * - calling clear results in the variable environment being empty
+ */ + @Test + public void testClearIsEmpty() { + // [ ] + assertTrue(ve.isEmpty()); + // [n1 -> v1] + ve.assign(n1, v1); + assertFalse(ve.isEmpty()); + // [ ] + ve.clear(); + assertTrue(ve.isEmpty()); + // [ ][ ] + ve.pushFrame(false); + assertFalse(ve.isEmpty()); + // [ ] + ve.popFrame(); + assertTrue(ve.isEmpty()); + } + + + /** + * tests pushFrame, popFrame + *

+ * - after pushing a new frame, new assignments happen there
+ * - mappings in a popped frame are gone
+ */ + @Test + public void testPushPopFrame() { + // [ ][ ] + ve.pushFrame(false); + // [ ][n1 -> v1] + ve.assign(n1, v1); + assertEquals(ve.lookUp(n1), v1); + // [ ] + ve.popFrame(); + assertNull(ve.lookUp(n1)); + // [n1 -> v1] + ve.assign(n1, v1); + assertEquals(ve.lookUp(n1), v1); + } + + + /** + * tests assign and lookup methods + *

+ * - assignments should only occur on the most recent level
+ * - previous assignments on that level should be updated in the most + * recent frame
+ */ + @Test + public void testAssignLookUp() { + // [n1 -> v1] + ve.assign(n1, v1); + assertEquals(ve.lookUp(n1), v1); + // [n1 -> v2] + ve.assign(n1, v2); + assertEquals(ve.lookUp(n1), v2); + // [n1 -> v2, n2 -> v2] + ve.assign(n2, v2); + assertEquals(ve.lookUp(n1), v2); + assertEquals(ve.lookUp(n2), v2); + // [n1 -> v2, n2 -> v2][n1 -> v3, n2 -> v3, n3 -> v1] + ve.pushFrame(false); + ve.assign(n1, v3); + ve.assign(n2, v3); + ve.assign(n3, v1); + assertEquals(ve.lookUp(n1), v3); + assertEquals(ve.lookUp(n2), v3); + assertEquals(ve.lookUp(n3), v1); + // [n1 -> v2, n2 -> v2] + ve.popFrame(); + assertEquals(ve.lookUp(n1), v2); + assertEquals(ve.lookUp(n2), v2); + assertEquals(ve.lookUp(n3), vUnassigned); + } + + + /** + * tests undefineReferencesTo, getTopLevelReferencesTo + *

+ * - all variables - disregarding the containing the level or frame - + * reference to the undefined value after undefineReferencesTo
+ * - getTopLevelReferencesTo returns the names of all variables in the + * first frame of the first level which refer to the specified object
+ */ + @Test + public void testObjectReferences() { + MObject object = null; + ModelFactory mf = new ModelFactory(); + MModel model = mf.createModel("m"); + MClass cls = mf.createClass("c", false); + try { + model.addClass(cls); + } catch (MInvalidModelException e) { + fail(e.getMessage()); + } + MSystem system = new MSystem(model); + try { + object = system.state().createObject(cls, "o"); + } catch (MSystemException e) { + fail(e.getMessage()); + } + + Value vO = object.value(); + Value vU = UndefinedValue.instance; + + // [n1 -> vO1] + ve.assign(n1, vO); + assertTrue(ve.getTopLevelReferencesTo(object).contains(n1)); + // [n1 -> vU] + ve.undefineReferencesTo(object); + assertEquals(ve.lookUp(n1), vU); + // [n1 -> vO1, n2 -> vO1] + ve.assign(n1, vO); + ve.assign(n2, vO); + assertTrue(ve.getTopLevelReferencesTo(object).contains(n1)); + assertTrue(ve.getTopLevelReferencesTo(object).contains(n2)); + // [n1 -> vU, n2 -> vU] + ve.undefineReferencesTo(object); + assertEquals(ve.lookUp(n1), vU); + assertEquals(ve.lookUp(n2), vU); + // [n1 -> vO1][n2 -> vO1] + // [n1 -> vO1, n2 -> vO1] + ve.assign(n1, vO); + ve.assign(n2, vO); + ve.pushFrame(false); + ve.assign(n1, vO); + ve.pushFrame(false); + ve.assign(n2, vO); + // [n1 -> vU][n2 -> vU] + // [n1 -> vU, n2 -> vU] + ve.undefineReferencesTo(object); + assertEquals(ve.lookUp(n2), vU); + // [n1 -> vU] + // [n1 -> vU, n2 -> vU] + ve.popFrame(); + assertEquals(ve.lookUp(n1), vU); + // [n1 -> vU, n2 -> vU] + ve.popFrame(); + assertEquals(ve.lookUp(n1), vU); + assertEquals(ve.lookUp(n2), vU); + } + + + /** + * tests remove + *

+ * - removes a mapping in the most recent frame
+ */ + @Test + public void testRemove() { + // [n1 -> v1] + ve.assign(n1, v1); + assertEquals(ve.lookUp(n1), v1); + // [ ] + ve.remove(n1); + assertEquals(ve.lookUp(n1), vUnassigned); + // [n1 -> v1][n1 -> v2] + ve.assign(n1, v1); + ve.pushFrame(false); + ve.assign(n1, v2); + assertEquals(ve.lookUp(n1), v2); + // [n -> v1][ ] + ve.remove(n1); + assertEquals(ve.lookUp(n1), vUnassigned); + // [n -> v1] + ve.popFrame(); + assertEquals(ve.lookUp(n1), v1); + } + + + /** + * test constructSymbolTable + *

+ * - name -> value mappings are transformed to corresponding + * name -> TypeOf(value) mappings
+ * - the symbol table in constructed only by mappings in the most recent + * frame
+ */ + @Test + public void testConstructSymbolTable() { + // VE + // [n1 -> v1, n2 -> v2, n3 -> v3] + ve.assign(n1, v1); + ve.assign(n2, v2); + ve.assign(n3, v3); + // ST + // [n1 -> Type(v1), n2 -> Type(v2), n3 -> Type(v3)] + SymbolTable st = ve.constructSymbolTable(); + assertEquals(st.getType(n1), v1.type()); + assertEquals(st.getType(n2), v2.type()); + assertEquals(st.getType(n3), v3.type()); + // VE + // [n1 -> v1, n2 -> v2, n3 -> v3][n1 -> v2, n2 -> v3, n3 -> v1] + ve.pushFrame(false); + ve.assign(n1, v2); + ve.assign(n2, v3); + ve.assign(n3, v1); + // ST + // [n1 -> Type(v2), n2 -> Type(v3), n3 -> Type(v1)] + st = ve.constructSymbolTable(); + assertEquals(st.getType(n1), v2.type()); + assertEquals(st.getType(n2), v3.type()); + assertEquals(st.getType(n3), v1.type()); + } + + + /** + * tests constructVarBindings + *

+ * - all mappings in the current frame get copied
+ */ + @Test + public void testConstructVarBindings() { + VarBindings vb; + // VE + // [n1 -> v1, n2 -> v2, n3 -> v3] + ve.assign(n1, v1); + ve.assign(n2, v2); + ve.assign(n3, v3); + // VB + // [n1 -> v1, n2 -> v2, n3 -> v3] + vb = ve.constructVarBindings(); + assertEquals(vb.getValue(n1), v1); + assertEquals(vb.getValue(n2), v2); + assertEquals(vb.getValue(n3), v3); + // VE + // [n1 -> v1, n2 -> v2, n3 -> v3][n1 -> v2, n2 -> v3, n3 -> v1] + ve.pushFrame(false); + ve.assign(n1, v2); + ve.assign(n2, v3); + ve.assign(n3, v1); + // VB + // [n1 -> v2, n2 -> v3, n3 -> v1] + vb = ve.constructVarBindings(); + assertEquals(vb.getValue(n1), v2); + assertEquals(vb.getValue(n2), v3); + assertEquals(vb.getValue(n3), v1); + } + + // TODO lookup, constructVBetc with visible objects +} diff --git a/use-core/src/test/java/org/tzi/use/util/soil/VariableSetTest.java b/use-core/src/test/java/org/tzi/use/util/soil/VariableSetTest.java new file mode 100644 index 000000000..2bafb505f --- /dev/null +++ b/use-core/src/test/java/org/tzi/use/util/soil/VariableSetTest.java @@ -0,0 +1,243 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util.soil; + +import java.util.Random; + +import junit.framework.TestCase; + +import org.junit.Before; +import org.junit.Test; +import org.tzi.use.uml.ocl.type.Type; +import org.tzi.use.uml.ocl.type.TypeFactory; + + +/** + * Test cases for the special set operations of {@code VariableSet}s + * + * @author Daniel Gent + * @see VariableSet + */ +public class VariableSetTest extends TestCase { + /** {@code VariableSet} A */ + private VariableSet fA; + /** {@code VariableSet} B */ + private VariableSet fB; + + + /** + * constructs the fixtures + */ + @Override + @Before + public void setUp() { + + // fill A and B with some random data + Type[] types = { + TypeFactory.mkInteger(), + TypeFactory.mkReal(), + TypeFactory.mkString(), + TypeFactory.mkBoolean(), + TypeFactory.mkOclAny(), + }; + + String[] names = { + "v00", "v01", "v02", "v03", "v04", "v05", "v06", "v07", "v08", + "v09", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", + "v18", "v19" + }; + + int numElems = 10; + Random random = new Random(); + + fA = new VariableSet(); + for (int i = 0; i < numElems; ++i) { + fA.add( + // the last 5 names are exclusively in B + names[random.nextInt(names.length - 5)], + types[random.nextInt(types.length)]); + } + + fB = new VariableSet(); + for (int i = 0; i < numElems; ++i) { + fB.add( + // the first 5 names are exclusively in A + names[5 + random.nextInt(names.length - 5)], + types[random.nextInt(types.length)]); + } + + // make sure there is an element in one set, which is not in the other + fA.add("aExclusive", types[random.nextInt(types.length)]); + fB.add("bExclusive", types[random.nextInt(types.length)]); + + // make sure A and B have at least one element in common + Type commonType = types[random.nextInt(types.length)]; + fA.add("common", commonType); + fB.add("common", commonType); + + // something to do for polydiff2... + Type integerType = TypeFactory.mkInteger(); + Type realType = TypeFactory.mkReal(); + // just to make sure... + assertTrue(integerType.conformsTo(realType)); + + fA.add("aInt_bReal", integerType); + fB.add("aInt_bReal", realType); + + fA.add("aReal_bInt", realType); + fB.add("aReal_bInt", integerType); + } + + + /** + * tests {@link VariableSet#add(VariableSet) Union} respectively + * {@link VariableSet#add(VariableSet) add} + */ + @Test + public void testUnion() { + VariableSet result = VariableSet.union(fA, fB); + + // everything in A must be in the result + assertTrue(result.containsAll(fA)); + + // everything in B must be in the result + assertTrue(result.containsAll(fB)); + + // everything in the result must be in either A or B + for (String name : result.getNames()) { + for (Type type : result.getTypes(name)) { + assertTrue(fA.contains(name, type) || fB.contains(name, type)); + } + } + } + + + /** + * tests {@link VariableSet#difference(VariableSet, VariableSet) Difference} + * respectively {@link VariableSet#add(VariableSet) remove} + */ + @Test + public void testDifference() { + VariableSet diffAB = VariableSet.difference(fA, fB); + + // everything in the difference must be in A + assertTrue(fA.containsAll(diffAB)); + + // nothing in B might be in the difference + for (String name : fB.getNames()) { + for (Type type : fB.getTypes(name)) { + assertFalse(diffAB.contains(name, type)); + } + } + + VariableSet diffBA = VariableSet.difference(fB, fA); + + // everything in the difference must be in B + assertTrue(fB.containsAll(diffBA)); + + // nothing in A might be in the difference + for (String name : fA.getNames()) { + for (Type type : fA.getTypes(name)) { + assertFalse(diffBA.contains(name, type)); + } + } + } + + + /** + * tests + * {@link VariableSet#polymorphicDifference1(VariableSet, VariableSet) + * PolymorphicDifference1} + * respectively + * {@link VariableSet#removePolymorphic1(VariableSet) removePolymorphic1} + */ + @Test + public void testPolymorphicDifference1() { + VariableSet pDiff1 = VariableSet.polymorphicDifference1(fA, fB); + + // everything in pDiff1 must be in A + assertTrue(fA.containsAll(pDiff1)); + + // the normal difference is a subset of the first polymorphic difference + // (it removes everything a normal difference would + possibly some more) + // we want to take a look everything that gets only removed by the + // first polymorphic difference + + VariableSet diff = VariableSet.difference(fA, fB); + VariableSet pDiffExcl = VariableSet.difference(diff, pDiff1); + + // for each element in pDiffExcl the following must hold: + // - element of vA + // - not element of vB + // - vB has a variable with that name + for (String name : pDiffExcl.getNames()) { + for (Type type : pDiffExcl.getTypes(name)) { + assertTrue(fA.contains(name, type)); + assertFalse(fB.contains(name, type)); + assertTrue(fB.contains(name)); + } + } + } + + + /** + * tests + * {@link VariableSet#polymorphicDifference2(VariableSet, VariableSet) + * PolymorphicDifference2} + * respectively + * {@link VariableSet#removePolymorphic2(VariableSet) removePolymorphic2} + */ + @Test + public void testPolymorphicDifference2() { + VariableSet pDiff2 = VariableSet.polymorphicDifference2(fA, fB); + + // everything in pDiff2 must be in A + assertTrue(fA.containsAll(pDiff2)); + + // the normal difference is a subset of the second polymorphic difference + // (it removes everything a normal difference would + possibly some more) + // we want to take a look everything that gets only removed by the + // second polymorphic difference + + VariableSet diff = VariableSet.difference(fA, fB); + VariableSet pDiffExcl = VariableSet.difference(diff, pDiff2); + + // for each element in pDiffExcl the following must hold: + // - element of A + // - not element of B + // - B has a variable with that name + // - one of its types must be a subtype of the current elements type + for (String name : pDiffExcl.getNames()) { + for (Type type : pDiffExcl.getTypes(name)) { + assertTrue(fA.contains(name, type)); + assertFalse(fB.contains(name, type)); + assertTrue(fB.contains(name)); + boolean containsSubType = false; + for (Type otherType : fB.getTypes(name)) { + if (otherType.conformsTo(type)) { + containsSubType = true; + break; + } + } + assertTrue(containsSubType); + } + } + } +} diff --git a/use-gui/src/it/java/org/tzi/use/main/ShellIT.java b/use-gui/src/it/java/org/tzi/use/main/ShellIT.java new file mode 100644 index 000000000..df4992dde --- /dev/null +++ b/use-gui/src/it/java/org/tzi/use/main/ShellIT.java @@ -0,0 +1,304 @@ +package org.tzi.use.main; + +import com.github.difflib.text.DiffRow; +import com.github.difflib.text.DiffRowGenerator; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.TestFactory; +import org.tzi.use.config.Options; +import org.tzi.use.util.USEWriter; + +import java.io.ByteArrayOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.fail; + +/** + * This class implements the shell integration tests. + * + *

These tests represent nearly the exact behavior of the + * USE shell. Only some whitespace differences and time outputs are ignored.

+ * + *

Each test consists of the following files: + *

    + *
  1. a model file (suffix {@code .use}) - this file provides the (possible empty) model used + * for the tests
  2. + *
  3. an input file (suffix: {@code .in}) - this file can contain any commands USE supports. + * The expected output must be specified by starting a line with a star {@code *}
  4. + *
  5. any other used file from the command line, e.g., ASSL- or command-files.
  6. + *

+ * + *

All {@code .use and .in} files must share the same name, e.g., t555.use and t555.in for test + * case 555. These files must be placed in the folder {@code it/resources/testfiles/shell}.

+ * + *

If an integration test fails, two additional files are created: + *

    + *
  1. {@code {testcasename}.expected - The expected output calculated from the {testcase}.in}-file
  2. + *
  3. {@code {testcasename}.actual} - The output captured while running the test.
  4. + *
+ * These files can be used to easily diff expected and current output.

+ */ +public class ShellIT { + + /** + * This TestFactory enumerates the {@code .in
-files in th folder testfiles/shell}. + * For each file a {@code DynamicTest} is created with the name of the file. + * + * @return A {@code Stream with one DynamicTest for each *.in}-file. + */ + @TestFactory + public Stream evaluateExpressionFiles() { + URL testDirURL = getClass().getClassLoader().getResource("testfiles/shell"); + Path testDirPath = null; + + if (testDirURL == null) { + fail("Directory for shell integration tests not found!"); + } + + try { + testDirPath = Path.of(testDirURL.toURI()); + } catch (URISyntaxException e) { + fail("Directory for shell integration tests not found!"); + } + + try { + return Files.walk(testDirPath).filter( + path -> path.getFileName().toString().endsWith(".in") + ).map(mapInFileToTest()); + } catch (IOException e) { + fail("Error iterating shell integration test input files!"); + } + + return Stream.empty(); + } + + /** + * This {@code Function} is used to map + * a given testinput-file given as a {@code Path} + * to a {@code DynamicTest}. + * + * @return A {@code DynamicTest that uses the function assertShellExpression} + * to test the given testinput file. + */ + private Function mapInFileToTest() { + return path -> { + final String modelFilename = path.getFileName().toString().replace(".in", ".use"); + final Path modelPath = path.resolveSibling(modelFilename); + + return DynamicTest.dynamicTest(path.getFileName().toString(), path.toUri(), () -> assertShellExpressions(path, modelPath)); + }; + } + + /** + *

This function controls the overall process for test for a single testfile.

+ * + *

The process is as follows: + *

    + *
  1. a command file and the expected output are created by examining the input file (via {@code createCommandFile}.
  2. + *
  3. USE is executed using the {@code useFile and the created command file (runUSE}).
  4. + *
  5. The output of USE is compared to the expected output created in 1. ({@code validateOutput}).
  6. + *

+ * + * @param testFile {@code Path} to the test input file to execute. + * @param useFile {@code Path} to the USE file containing the model to load for the test. + */ + private void assertShellExpressions(Path testFile, Path useFile) { + + Path cmdFile = testFile.resolveSibling(testFile.getFileName() + ".cmd"); + + List expectedOutput = createCommandFile(testFile, cmdFile); + + List actualOutput = runUSE(useFile, cmdFile).collect(Collectors.toList()); + + validateOutput(testFile, expectedOutput, actualOutput); + } + + /** + * Compares the two lists of strings {@code expectedOutput} + * and {@code actualOutput}. + * If they differ, two files are written at the location of the + * {@code testFile. One with the expected output (.expected}) + * and one with the actual output ({@code .actual}). + * + * @param testFile The {@code Path to the testFile} + * @param expectedOutput List of strings with the expected output (one String per line) + * @param actualOutput List of strings with the actual output (one String per line) + */ + private void validateOutput(Path testFile, List expectedOutput, List actualOutput) { + //create a configured DiffRowGenerator + DiffRowGenerator generator = DiffRowGenerator.create() + .showInlineDiffs(true) + .mergeOriginalRevised(true) + .inlineDiffByWord(true) + .ignoreWhiteSpaces(true) + .lineNormalizer( (s) -> s ) // No normalization required + .oldTag((f, start) -> start ? "-\033[9m" : "\033[m-") //introduce markdown style for strikethrough + .newTag((f, start) -> start ? "+\033[97;42m" : "\033[m+") //introduce markdown style for bold + .build(); + + //compute the differences for two test texts. + List rows = generator.generateDiffRows(expectedOutput, actualOutput); + Predicate filter = d -> d.getTag() != DiffRow.Tag.EQUAL; + + if (rows.stream().anyMatch(filter)) { + StringBuilder diffMsg = new StringBuilder("USE output does not match expected output!").append(System.lineSeparator()); + + diffMsg.append("Testfile: ").append(testFile).append(System.lineSeparator()); + + diffMsg.append(System.lineSeparator()).append("Note: the position is not the position in the input file!"); + diffMsg.append(System.lineSeparator()).append(System.lineSeparator()); + + rows.stream().filter(filter).forEach( + row ->diffMsg.append(System.lineSeparator()).append(row.getOldLine()) + ); + + writeToFile(expectedOutput, testFile.getParent().resolve(testFile.getFileName().toString() + ".expected")); + writeToFile(actualOutput, testFile.getParent().resolve(testFile.getFileName().toString() + ".actual")); + + fail(diffMsg.toString()); + } + } + + /** + *

Helper method that writes the list of strings {@code data} + * to the file located by the {@code Path} {@code file}.

+ * + *

If the file is not accessible, i.e., an IOException is thrown, + * the exceptions is caught and the test case fails.

+ * @param data The {@code List} of string (lines) to write. + * @param file The path to the file to write (file is overwritten). + */ + private void writeToFile(List data, Path file) { + try (FileWriter writer = new FileWriter(file.toFile())) { + + for (String line : data) { + writer.write(line); + writer.write(System.lineSeparator()); + } + } catch (IOException e) { + fail("Testoutput could not be written!", e); + } + } + + /** + * Creates a USE-command file at the position located by the path {@code cmdFile}. + * The file contains all commands that are specified in the {@code inFile}. + * The expected output, i.e., lines starting with a {@code *} are added to the list {@code expectedOutput}. + * + * @param inFile The {@code Path} to the test input file. + * @param cmdFile The {@code Path} where to create the command file. + * @return A {@code List} which is filled with the expected output of USE. + */ + private List createCommandFile(Path inFile, Path cmdFile) { + List expectedOutput = new LinkedList<>(); + + // Build USE command file and build expected output + try ( + Stream linesStream = Files.lines(inFile, StandardCharsets.UTF_8); + FileWriter cmdWriter = new FileWriter(cmdFile.toFile(), StandardCharsets.UTF_8, false) + ) { + + linesStream.forEach(inputLine -> { + + // Ignore empty lines in expected, since they are also suppressed in actual output + if (inputLine.isBlank()) + return; + + if ((inputLine.startsWith("*") || inputLine.startsWith("#")) + && inputLine.substring(1).isBlank()) { + return; + } + + if (inputLine.startsWith("*")) { + // Input line minus prefix(*) is expected output + expectedOutput.add(inputLine.substring(1).trim()); + } else if (!inputLine.startsWith("#")) { // Not a comment + try { + cmdWriter.write(inputLine); + cmdWriter.write(System.lineSeparator()); + + // Multi line commands (backslash and dot) are ignored + if (!inputLine.matches("^[\\\\.]$")) { + expectedOutput.add(inputLine); + } + } catch (IOException e1) { + fail("Could not write USE command file for test!", e1); + } + } + }); + } catch (IOException e) { + fail("Could not write USE command file for test!", e); + } + + return expectedOutput; + } + + /** + * Executes USE with the given {@code useFile} as the model + * and the {@code cmdFile} to execute commands. + * The output is captured from the output and error streams. + * + * @param useFile Path to the USE model to load on startup + * @param cmdFile Path to the commands file to execute + * @return A {@code List} of strings. Each string is one line of output. + */ + private Stream runUSE(Path useFile, Path cmdFile) { + + // We need to specify a concrete locale to always get the same formatted result + Locale.setDefault(new Locale("en", "US")); + + Options.resetOptions(); + USEWriter.getInstance().clearLog(); + + String homeDir = null; + try { + homeDir = useFile.getParent().resolve("../../../../../use-core/target/classes").toFile().getCanonicalPath(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + String[] args = new String[] { + "-nogui", + "-nr", + "-t", + "-it", + "-q", + "-oclAnyCollectionsChecks:E", + "-extendedTypeSystemChecks:E", + /* This is currently an unstable workaround + USE determines the plugin and the extensions to OCL by fixed paths. + For now, the use-core module contains the directories including the extensions + and an empty plugins folder. + The folder is located: use/use-core/target/classes + Therefore, this is used as the USE home + */ + "-H=" + homeDir, + useFile.toString(), + cmdFile.toString()}; + + Main.main(args); + + try (ByteArrayOutputStream protocol = new ByteArrayOutputStream();) { + USEWriter.getInstance().writeProtocolFile(protocol); + String output = protocol.toString(); + return output.lines().filter(l -> !l.isBlank()); + } catch (IOException e) { + fail(e); + } + + return Collections.emptyList().stream(); + } +} diff --git a/use-gui/src/main/java/org/tzi/use/main/Main.java b/use-gui/src/main/java/org/tzi/use/main/Main.java new file mode 100644 index 000000000..5a70ef8ad --- /dev/null +++ b/use-gui/src/main/java/org/tzi/use/main/Main.java @@ -0,0 +1,259 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2004 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.main; + +import org.tzi.use.config.Options; +import org.tzi.use.gui.main.MainWindow; +import org.tzi.use.main.runtime.IRuntime; +import org.tzi.use.main.shell.Shell; +import org.tzi.use.parser.use.USECompiler; +import org.tzi.use.uml.mm.MMPrintVisitor; +import org.tzi.use.uml.mm.MMVisitor; +import org.tzi.use.uml.mm.MModel; +import org.tzi.use.uml.mm.ModelFactory; +import org.tzi.use.uml.ocl.extension.ExtensionManager; +import org.tzi.use.uml.sys.MSystem; +import org.tzi.use.util.Log; +import org.tzi.use.util.USEWriter; + +import javax.swing.*; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.awt.*; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Method; +import java.nio.file.Path; + +/** + * Main class. + * + * @author Mark Richters + */ +public final class Main { + + // utility class + private Main() { + } + + private static void initGUIdefaults() { + MetalLookAndFeel.setCurrentTheme(new MyTheme()); + } + + public static void main(String[] args) { + // set System.out to the OldUSEWriter to protocol the output. + System.setOut(USEWriter.getInstance().getOut()); + // set System.err to the OldUSEWriter to protocol the output. + System.setErr(USEWriter.getInstance().getErr()); + + // read and set global options, setup application properties + Options.processArgs(args); + if (Options.doGUI) { + initGUIdefaults(); + } + + Session session = new Session(); + IRuntime pluginRuntime = null; + MModel model = null; + MSystem system = null; + + if (!Options.disableExtensions) { + ExtensionManager.EXTENSIONS_FOLDER = Options.homeDir + Options.FILE_SEPARATOR + + "oclextensions"; + ExtensionManager.getInstance().loadExtensions(); + } + + // Plugin Framework + if (Options.doPLUGIN) { + // create URL from plugin directory + Path pluginDirURL = Options.pluginDir; + Log.verbose("Plugin path: [" + pluginDirURL + "]"); + Class mainPluginRuntimeClass = null; + try { + mainPluginRuntimeClass = Class + .forName("org.tzi.use.runtime.MainPluginRuntime"); + } catch (ClassNotFoundException e) { + Log + .error("Could not load PluginRuntime. Probably use-runtime-...jar is missing.\n" + + "Try starting use with -noplugins switch.\n" + + e.getMessage()); + System.exit(1); + } + try { + Method run = mainPluginRuntimeClass.getMethod("run", + new Class[] { Path.class }); + pluginRuntime = (IRuntime) run.invoke(null, + new Object[] { pluginDirURL }); + Log.debug("Starting plugin runtime, got class [" + + pluginRuntime.getClass() + "]"); + } catch (Exception e) { + e.printStackTrace(); + Log.error("FATAL ERROR."); + System.exit(1); + } + } + + // compile spec if filename given as argument + if (Options.specFilename != null) { + Path file = Path.of(Options.specFilename); + + try (FileInputStream specStream = new FileInputStream(Options.specFilename)){ + Log.verbose("compiling specification..."); + model = USECompiler.compileSpecification(specStream, + file.getFileName().toString(), new PrintWriter(System.err), + new ModelFactory()); + } catch (FileNotFoundException e) { + Log.error("File `" + Options.specFilename + "' not found."); + if (Options.integrationTestMode) { + return; + } else { + System.exit(1); + } + } catch (IOException e1) { + // close failed + } + + // compile errors? + if (model == null) { + if (Options.integrationTestMode) { + return; + } else { + System.exit(1); + } + } + + if(!Options.quiet){ + Options.setLastDirectory(new java.io.File(Options.specFilename).getAbsoluteFile().toPath().getParent()); + } + if (!Options.testMode) + Options.getRecentFiles().push(Options.specFilename); + + if (Options.compileOnly) { + Log.verbose("no errors."); + if (Options.compileAndPrint) { + MMVisitor v = new MMPrintVisitor(new PrintWriter( + System.out, true)); + model.processWithVisitor(v); + } + System.exit(0); + } + + // print some info about model + Log.verbose(model.getStats()); + + // create system + system = new MSystem(model); + } + session.setSystem(system); + + if (Options.doGUI) { + if (pluginRuntime == null) { + Log.debug("Starting gui without plugin runtime!"); + MainWindow.create(session); + } else { + Log.debug("Starting gui with plugin runtime."); + MainWindow.create(session, pluginRuntime); + } + } + + // create thread for shell + Shell.createInstance(session, pluginRuntime); + Shell sh = Shell.getInstance(); + Thread t = new Thread(sh); + t.start(); + + // wait on exit from shell (this thread never returns) + try { + t.join(); + } catch (InterruptedException ex) { + // ignored + } + } +} + +/** + * A theme with full control over fonts and customized tree display. + */ +class MyTheme extends DefaultMetalTheme { + private FontUIResource controlFont; + + private FontUIResource systemFont; + + private FontUIResource userFont; + + private FontUIResource smallFont; + + MyTheme() { + // System.out.println("font: " + Font.getFont("use.gui.controlFont")); + controlFont = new FontUIResource(Font.getFont("use.gui.controlFont", + super.getControlTextFont())); + systemFont = new FontUIResource(Font.getFont("use.gui.systemFont", + super.getSystemTextFont())); + userFont = new FontUIResource(Font.getFont("use.gui.userFont", super + .getUserTextFont())); + smallFont = new FontUIResource(Font.getFont("use.gui.smallFont", super + .getSubTextFont())); + } + + public String getName() { + return "USE"; + } + + public FontUIResource getControlTextFont() { + return controlFont; + } + + public FontUIResource getSystemTextFont() { + return systemFont; + } + + public FontUIResource getUserTextFont() { + return userFont; + } + + public FontUIResource getMenuTextFont() { + return controlFont; + } + + public FontUIResource getWindowTitleFont() { + return controlFont; + } + + public FontUIResource getSubTextFont() { + return smallFont; + } + + public void addCustomEntriesToTable(UIDefaults table) { + initIcon(table, "Tree.expandedIcon", "TreeExpanded.gif"); + initIcon(table, "Tree.collapsedIcon", "TreeCollapsed.gif"); + initIcon(table, "Tree.leafIcon", "TreeLeaf.gif"); + initIcon(table, "Tree.openIcon", "TreeOpen.gif"); + initIcon(table, "Tree.closedIcon", "TreeClosed.gif"); + table.put("Desktop.background", table.get("Menu.background")); + } + + private void initIcon(UIDefaults table, String property, String iconFilename) { + table.put(property, new ImageIcon(getClass().getResource("/images/" + iconFilename))); + } + +} diff --git a/use-gui/src/main/java/org/tzi/use/util/input/ShellReadline.java b/use-gui/src/main/java/org/tzi/use/util/input/ShellReadline.java new file mode 100644 index 000000000..03c17e035 --- /dev/null +++ b/use-gui/src/main/java/org/tzi/use/util/input/ShellReadline.java @@ -0,0 +1,71 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util.input; + +import java.io.IOException; + +import org.tzi.use.main.shell.Shell; + +/** + * A {@link Readline} implementation that reads input from the {@link Shell} + * using the current readline that is on top of the readline stack. This might + * either be interactive or from an open soil file. + * + * @author Frank Hilken + */ +public class ShellReadline implements Readline { + + private Shell shell; + + public ShellReadline(Shell useShell) { + shell = useShell; + } + + @Override + public String readline(String prompt) throws IOException { + if(shell == null){ + throw new IOException("Stream closed"); + } + return shell.readline(prompt); + } + + @Override + public void usingHistory() { + } + + @Override + public void readHistory(String filename) throws IOException { + } + + @Override + public void writeHistory(String filename) throws IOException { + } + + @Override + public void close() throws IOException { + shell = null; + } + + @Override + public boolean doEcho() { + return false; + } + +} diff --git a/use-gui/src/main/resources/images/use1.gif b/use-gui/src/main/resources/images/use1.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b947ed7150d1815e38b91f375cf764dc0eb1d50 GIT binary patch literal 1706 zcmbV{i&v9}8OA?85=h9!B#`T|m_&$8fbq$tT!!a_$R!aN7fFhM+Xn>XA{`<+gRTuU zK}=FEa{Gu>xrqdDq7JJJw*&+Gpde6!q}4eXVr8rwt;|N-vBmxgd(L@(&-0%1p68r5 zUKSS~k#iJ)fPVu3>TsYA6#Z!s)PbNVf;bSwNd!hw7;(UelL!o>Fzh4@Ar1&ZAq0V7 z2Lz)K>XkTW>tEQXzc002M`07e1WNf>}o073xB8Qxw101W(O4u`|J{NLj3 zkdtzh`P|;|x1Ddl1l)GaEoD-FPCeRNK6O0u%6xytq3fA9 z>_ewN|1CIbzj62V(Uvw)-3h--!8{CnlDOyb#>3E6v3;%)EX9<%ON&7QT}NlreHbL{ zp%QnjdmGYj#I?C930_@PsHxal6~2}z5=$umm`>%oDd3x zxFnG3N$n=ffKHQ%cR8j+?_;3zSq2uH$G$tnzdtt4`QrqeBmB-fwJQnJy+9Ss43Vg5 zrs>XVoEjX4b8uDBG1!v~X<{&6&HMxL{*xjx&%Zrh^`BM%b=OHk=-<}?lvA@Y(Y#`Y zwtpDv#uA9Z;pdtylAXqn?+5L?i5PSEjkv8f2kn6(uz(jNe{~hI{UKkjey4nIg}`|8EzXQ)<+WhSANE_jNd)UEHF%( z7Ck@xETBQH1CM=#f!hz3_KIWdjPNGx))`ju5^ng$)882{aIXE3zSYP2hSSpqka3D; zNz`BsjDM4rYR-*%xOS6eU*ZQx zXeirE5*9On@i?LHOoxkt<$Nu`=y#Yya?M?C-pM%lVgW9<4=4JwrMEV0kLZ?pPh$Eu zf+t!x09V}1kz*wllhNveosB|@Nbe)mD5^t)^Z{h~cwhRa%`Gu%ir7Rv@L>?$BjFdf zf&^GAepJH8H>QwtyCa7SXoPIr!$3jVmcrvt6%?i(`Br%45T_0=|IqIotC7!I@fu2E zq!-s5c{TFDC9A3Bg)lTuCrP0tO<`KD+@9r=57v&mG4Qn1-xD(b@gt2LwbL{j;^Ph*aF4&<+TN9TKxCp8tJnK!onO*>L;o`lX%mErOiti zW;L5}_|+G^YXIY3-Us`Kj0wqSxA|SG3uVEW;+J zDLP&GB@}}-a|n|ungg>-!#<+htuD_ql$M!{*z*g4-<0mpQVl#i%I$|vo}S|ncBiO> zGUAFlG9r((Xge8vK-;z)vlgz%_q*78zUp-^Mt9&s<)s}8X1n^)^-Le;SK`e+ru`sG zqv{D?hs$2QSCi%Sw>b-?wVdwK8Zh3l-&b??&J)Ejk*ogKOoH^?(Wcf5Sw3yLF?Qmz zZY20#Mfcv@QE8T!C1?Js&(CPT+K9&yx8gY0Q$7Y30quNq66hYT0m$4cO+!zPUzyo| z`)Vy%C?sJa!q?R_zNkgd47(>w9k}m$OH?L4FM6rwa?+Nq`!d&6 z)FEu(HkSHB1Gli^>?P)6HF2a}Z16rYwE<9BAuhk>g;1+T4WStPWa{Z0lf8%^p?QIl znk-T`!FsgyRV^8BY{I|q70voFVAW+TB|hAClf0|5Cicss`XJ>gtM^1~yJEj!+_(kQ zZ}ZuAdF#|-#c=PlxJ!O4^ZevghscHxGi`8YI~1&?eox|-;ab$!vboByUS5vHfxyrI E2b_JZ&Hw-a literal 0 HcmV?d00001 diff --git a/use-gui/src/test/java/org/tzi/use/util/DiagramUtilTest.java b/use-gui/src/test/java/org/tzi/use/util/DiagramUtilTest.java new file mode 100644 index 000000000..d84d8fe02 --- /dev/null +++ b/use-gui/src/test/java/org/tzi/use/util/DiagramUtilTest.java @@ -0,0 +1,130 @@ +/* + * USE - UML based specification environment + * Copyright (C) 1999-2010 Mark Richters, University of Bremen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.tzi.use.util; + +import java.awt.geom.Ellipse2D; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import junit.framework.TestCase; + +import org.junit.Test; +import org.tzi.use.gui.views.diagrams.util.Util; + +/** + * Test for diagram utilities (mainly geometry) + * @author Lars Hamann + * + */ +public class DiagramUtilTest extends TestCase { + @Test + public void testCircleIntersection() { + Ellipse2D circle = new Ellipse2D.Double(-4, -4, 8, 8); + Point2D res; + Point2D.Double expected = new Point2D.Double(); + + expected.x = 4; + expected.y = 0; + res = Util.intersectionPoint(circle, new Point2D.Double(4, 0)); + assertEquals(expected, res); + + expected.x = 0; + expected.y = 4; + res = Util.intersectionPoint(circle, new Point2D.Double(0, 4)); + assertEquals(expected, res); + + expected.x = -4; + expected.y = 0; + res = Util.intersectionPoint(circle, new Point2D.Double(-4, 0)); + assertEquals(expected, res); + + expected.x = 0; + expected.y = -4; + res = Util.intersectionPoint(circle, new Point2D.Double(0, -4)); + assertEquals(expected, res); + + res = Util.intersectionPoint(circle, new Point2D.Double(1.5, -2.5)); + Point2D res2 = Util.intersectionPoint(circle, res); + assertEquals(res, res2); + } + + public void testRectangleInterception() { + Rectangle2D.Double r = new Rectangle2D.Double(); + r.x = 0; + r.y = 0; + r.width = 1; + r.height = 1; + + Line2D.Double l = new Line2D.Double(); + l.x1 = 0.5; + l.y1 = 0.5; + + l.x2 = 1.5; + l.y2 = 0.5; + + Point2D res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(1.0, res.getX()); + assertEquals(0.5, res.getY()); + + l.x2 = 0.5; + l.y2 = 1.5; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(0.5, res.getX()); + assertEquals(1.0, res.getY()); + + l.x2 = -0.5; + l.y2 = 0.5; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(0.0, res.getX()); + assertEquals(50, Math.round(res.getY() * 100)); + + l.x2 = 0.5; + l.y2 = -1.5; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(0.5, res.getX()); + assertEquals(0.0, res.getY() * 100); + + // Test enlarge + l.x2 = 0.6; + l.y2 = 0.5; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(1.0, res.getX()); + assertEquals(0.5, res.getY()); + + l.x2 = 0.5; + l.y2 = 0.6; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(0.5, res.getX()); + assertEquals(1.0, res.getY()); + + l.x2 = 0.4; + l.y2 = 0.5; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(0.0, res.getX()); + assertEquals(50, Math.round(res.getY() * 100)); + + l.x2 = 0.5; + l.y2 = 0.4; + res = Util.intersectionPoint(r, l.getP1(), l.getP2(), true); + assertEquals(0.5, res.getX()); + assertEquals(0.0, res.getY() * 100); + } +} From 88d6a613407f2ce9eade1a4daabe011188793a1b Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 10 Dec 2024 01:08:36 +0100 Subject: [PATCH 002/148] wrong graphql name, now fixed --- .../use/graphql/services/MClassGService.java | 2 +- .../services/MClassGService$MClassInput.class | Bin 2411 -> 2411 bytes .../use/graphql/services/MClassGService.class | Bin 1855 -> 2026 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java b/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java index 26d4b843c..9c9bed7af 100644 --- a/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java +++ b/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java @@ -27,7 +27,7 @@ public Iterable classes() { } @MutationMapping - public UseClass aClass(@Argument MClassInput mClassInput) { + public UseClass aUseClass(@Argument MClassInput mClassInput) { UseClass tmpUseClass = new UseClass(mClassInput.name_mclass, mClassInput.attributes,mClassInput.operations); return classRepo.save(tmpUseClass); } diff --git a/use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class b/use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class index 9541a7ea99c0899d130de247dc8fe4f9e110265e..c0cfbc898a2ff62dd7dbccc9c212b5b004a9bfc7 100644 GIT binary patch delta 53 zcmaDY^jc^G7dxZMWN!A!Kyp629helI{Fz+~$dco51Cps6Hb8O_hYOH=&d~w@pw$mG delta 53 zcmaDY^jc^G7dxZ!WN!A!Kyp629helI{Fz+~$dco51Cps6Hb8O_hYOH=&d~w@pePS6 diff --git a/use-api/target/classes/org/tzi/use/graphql/services/MClassGService.class b/use-api/target/classes/org/tzi/use/graphql/services/MClassGService.class index 17fb1e125944a873578ce59a3445320a425cf51b..cf74b4e71674b1109cb1121dbdfa0e41ffa92371 100644 GIT binary patch delta 625 zcmZvZOHUJF6o#K~N;~a1pb=ViKsy6fp;YSy6)lP)f)`MvUgFA3;-u6-+e}9jSKYc` zLuTc_FhVqFqHgs+n7HOg7|%=%Y+Ri4o$LFa^PO*fJNu2Fe?ET&Zt!Ts*y&^#Aghxz zImBVbftT)Ux4h~$YUS#icHpfk63thEBD)Z0>do?!UvC7}!1vs>N*YVi|J1XkQPp{FShJGZZ+k zbHd~#qoJdorwbHK#wmqw)o{MRX_GP~h0$zzz8ln=jkbZqS(7B^!XIiXHDPjri<|qj zb(PGxkK5knyTpu^yo6#h{GA-^T$XR?BO!W#9NZxcrQ_n2s0%)uwtyJZx8Fb*qWSTM&49MQa8m=%yR1=Y)ht(1}c7_ z|KO3241U3RHonD($e75fPn=ndC`;R%*Z7XJN84Q`Pa0dU;l%WI7j1WyB6G|OE)E9)ciuD(=bz$ZJ delta 453 zcmYLF$xZ@65PjVaGdLOWFfi(%fFo{z`-X}OsNDPjPliMeUc{(J6Mn#pnUC;l0*OK6 za`sdB2;=M4$f2rhdG%gZ_l7>=_Sg5zJAevm4|dPAkPz_0JHw9+!o#qI5eK8Jyos}@ zhcO4^NQXHYWISXYOdu^_H?JDk_1lZ)<&6y&lMW)tg$-FYrya~-w*4sYg*5B!l2MhB zISAy#mYHf5C>zHBeF6rOP=ZBf9wfbuc`Wc%(IOm92`pim_&jTCI%hB6fz?G!;E7cU z#c8q!_?k=2^|@9wW|h-Kwb)u`Ah3bWKiYGyt`-Vj;hq*cNYYZY%rk-$B~|QVO5zi4 zU(VL+W_UzaOJ;u={?`vs!WLB$Ja!v9L~D7}1j>}!rCI8@Jq8B$=_L*{Mln~IS80d3 QEBHA_jBMgPL~#uN2fa=&)&Kwi From 901dce79fcc9fafd1280f8fd795157c72285d9ff Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 10 Dec 2024 02:15:11 +0100 Subject: [PATCH 003/148] added duplication error --- .../main/java/org/tzi/use/rest/services/MClassRService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java index 4ca710434..38e58fa92 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java @@ -18,6 +18,9 @@ public class MClassRService { public UseClass saveMClass(UseClass aUseClass) throws MInvalidModelException, UseApiException { MClassFacade.createMClass(aUseClass); + if(classRepository.findById(aUseClass.getName_mclass()).isPresent()) { + throw new UseApiException("Class name already exists"); + } return classRepository.save(aUseClass); } From 93f7266a68af3b1aa81b44c15d473969acedc568 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 10 Dec 2024 02:15:19 +0100 Subject: [PATCH 004/148] now name is ID --- use-api/src/main/java/org/tzi/use/model/UseClass.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/model/UseClass.java b/use-api/src/main/java/org/tzi/use/model/UseClass.java index 27c69d053..f43624150 100644 --- a/use-api/src/main/java/org/tzi/use/model/UseClass.java +++ b/use-api/src/main/java/org/tzi/use/model/UseClass.java @@ -1,6 +1,7 @@ package org.tzi.use.model; import jakarta.persistence.*; +import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.ArrayList; @@ -10,8 +11,6 @@ public class UseClass { @Id - private String id; - private String name_mclass; // Unidirectional OneToMany relationship @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) From 33e888f85c3b8aa32975c7708762ecf94f2b73a3 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 10 Dec 2024 02:15:26 +0100 Subject: [PATCH 005/148] target --- .../services/MClassGService$MClassInput.class | Bin 2411 -> 2411 bytes .../use/graphql/services/MClassGService.class | Bin 2026 -> 1858 bytes .../classes/org/tzi/use/model/UseClass.class | Bin 2379 -> 2382 bytes .../use/rest/services/MClassRService.class | Bin 1237 -> 2296 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class b/use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class index c0cfbc898a2ff62dd7dbccc9c212b5b004a9bfc7..9541a7ea99c0899d130de247dc8fe4f9e110265e 100644 GIT binary patch delta 53 zcmaDY^jc^G7dxZ!WN!A!Kyp629helI{Fz+~$dco51Cps6Hb8O_hYOH=&d~w@pePS6 delta 53 zcmaDY^jc^G7dxZMWN!A!Kyp629helI{Fz+~$dco51Cps6Hb8O_hYOH=&d~w@pw$mG diff --git a/use-api/target/classes/org/tzi/use/graphql/services/MClassGService.class b/use-api/target/classes/org/tzi/use/graphql/services/MClassGService.class index cf74b4e71674b1109cb1121dbdfa0e41ffa92371..90b52ea789f258838497160b96941c5178655fa8 100644 GIT binary patch delta 445 zcmYLF$xZ@65PjXi40Z-Q42(J`;D{UGzAG+>a`OW`8522p5u+YW_y#i{;nhSEgGOUK zdi5{(2;=M4$f2rhdG%gZcl$q*>ht^g4L}w3JJq#pqy+r%HtHw(;9CJib;#$GQn1dJ!VMA7|2?vvydc2okk=Qf@iebyj zv`UmqB0`@+6lrLoGBXd7USS5ae04Mjhf@OcSRlU0+Oo;nE4E>GkPvuaRYG%G>;b;v z(sMnoMT1%5G*K}HQ*=hNVMP+bmMjcWbHY88# z9I`pgc+XRhvn70+GL_y-HCilj)TT;BVYNG96vWMTYt_QzxXm_B^uDR7{z;otoPM|6 z_>t+JL2*`Y;VOoFVEOAPzx*EajbsMr#1E1YKTIEaauhf(Ss_JJV@fjV;{vvDDK0WC zc+EMPdKWjP`?rfPw{cA*M`ZKs v+>nX?j&f7bx5P}n=)44dEQmL_oj@#!?nu5Ub~mXid98aAS%NQ#Y8~e{vJYU0 diff --git a/use-api/target/classes/org/tzi/use/model/UseClass.class b/use-api/target/classes/org/tzi/use/model/UseClass.class index a7959244849582f07ae0adb75caf9c7d9a631aa8..106b3e977237a85acd5b4d22fd28518bf38c83f7 100644 GIT binary patch delta 824 zcma)4NlpSm6n)hQjX1Z)#0hc6a=;M>6vT;*7f|D(6O|ZaW01s+35V#5Xw;1h51@%> z@Fd1p)g5e!3m5!f#jpQ{|NGtguwrjtFRuXd*nWuh2sbJE$C3x7axrytUA}ON=Vklq z?6y?COr6>lJ7qggsbW_yO3ve<=xC^hU?7YL1O^DAa-7*fBVvq$`kc_UIPXLJ4Ie|C zVFaTXJHj|7*pj@#Br7d}9{I1HXqDYlm}Z8z zo4^7V8C7$Z3Jm6moO*_M;K_jMRz5(XVMY0& ztO8OwbMMTdnRVVgx03rzXy1}sk_h>m&1j|#H9_~yES&r>i2jH~eeuB$(CAP2 zAI5WUD>iOvn3>xGpCGFQF|a13*oMAV5M9Ke)2_phFa{982sXH&O^$sFNo-3nleggDIUBpJ zCo=0iIo+CEUqbe6aw#eJ+(m9ks!iIg{i2soznFGBOeHey5_gXi+V?OOyE81hGX#4N z%1wxs{ajO!`5S diff --git a/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class b/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class index 4ffd776f2c0dae023ff486d51df4a1a55f9256ed..721065c02b6ce3340f1ac9fde2c6aec47f7c4466 100644 GIT binary patch literal 2296 zcmah~>v9xD7(JbYOfn3&5FkMe3j!wLGJvSa0vaNh;4Z-|1OXL0yPZvwxopk!2I7D$-mJKwec`sdZ}0H)A#(Su$GeIB-;Uts5Bxgz~Q zMooWq;jyY4f&Pm+(&n;2@A$;LivbKea6N2=ComExP2YU4{dTJS>U1E}^qQ>8h7$1V ziIPTjHU%z>SBkP>+)#mkH&xl4^2FN?2eBPH9PIS43qu0qMVv&X#!pqUqU$Qn8O+r> zYk?hg%VQR_! z5*QwzsJwPz%_KT%mbYR*-f?ii!@C$0C>0SmqaZM_sH4V})tLs(9WMZOVnTOiI@(4D z{%p(WIFbQ*mvG3zVGr-&h``WB5rILS-loe`#JDn?4+e1z?>iXxFoDUg=+{ zZOZQHDAcikn-&?`rDRwhzzG3Yr=?a0)5R(H4o-VGgR=s=GX~vv1e}&d2qJc1J;Gv9*0{cR_tfu3rF3mk{ zmN-j|j7<6l*czRJ@AEAOEQN!`5XzRenLO3fSD)5Z7LEaYCNP@iR4HP9lw?4UHC9XN zsZLGm;u5adiaTpl<8u#JaZR8vl`AZq|1&DL)84${VFowp5t}YkLBOc5Dohd{z*t4N7w{A=M{wvg|J?8KwTBtlO&b<@yDGs%_#Y zI#CV6_D!>hS!5L*sax%EK_z!2;Yp$r*JUs-6K&V|W}jKo)HnG?0seRSQiE$fverR7 z6Sgvs+Jdu6Hq;sOTduVffdgHdx+|C1+iFJEm#eas^K;jOmpXVLFi{L~I}H3V^s6%w zb5A#_wtKD1v)8c=(EZiv3fm1?)O0hFrk#-H=?ww7_%>dbt<|--oz&GeZGE}BWByuC zJ7tY#Q`j_Wtk^`wX0@gKyaf_%=ao1%sYzt3s?1W{NC!|C*hOcSUgzh9lGxD?AHA_ zHf$pPupqxlx#tkmG6-tgC>rn0M3G7|I~Bvq0y(52V1F8WyC`4Aj$Js!2dalX zM)1ogisKht^>eIn?B&R}mES5?K1acE%j9#2pE>ElEq?7W2s6vC*Ac*Ne94u-9Cv!M z%g+eb%e}kDU%^e}>&JG1`M?IQS#Z{(_@J+&bBH^a3ALd2r$tJ^|%U{)S8U zhdzCdsXsEYmzeIspBVm$z`YrnF*uwLll2~qU@za5eeCEXY+9qZjPgl z_PaSb$5Tqwd8+*s15!X@R%!?vt@*cG5Rk;$#JXz delta 395 zcmYjNyGjE=6g{)!?%=oyy{g87KS&W|u4Xe`89 zuoV0Qf5A#TGaJIlUWL+{r^pgjOAsY`3R=W(!EU|{!0-9)%2`qEs(FE8hTBB0>2z8j; zBbSaaD0z56?T+(IOS_#iO)E~Xn%#``c#RdTQg@9P0pAj|$vUXBw=O+0n?_rM5oQJc bw6mPGe>rt?EZlVgHYl>`x~<<|*am(8Hnb=@ From 826fef703072ae1d48e782a558c503b4294d8389 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 10 Dec 2024 09:31:50 +0100 Subject: [PATCH 006/148] new tests added the performance tests has to be sperarated --- .../use-webapi.postman_collection.json | 239 +++++++++++++++++- .../use/rest/services/MClassRService.class | Bin 2296 -> 1530 bytes .../use-webapi.postman_collection.json | 239 +++++++++++++++++- .../2024-12-10T09-19-19_942.dumpstream | 5 + .../2024-12-10T09-22-32_147.dumpstream | 5 + .../2024-12-10T09-23-54_430.dumpstream | 5 + 6 files changed, 489 insertions(+), 4 deletions(-) create mode 100644 use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream create mode 100644 use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream create mode 100644 use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream diff --git a/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json b/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json index 246729bbb..3555d7aa3 100644 --- a/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json +++ b/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json @@ -224,8 +224,11 @@ { "listen": "prerequest", "script": { - "packages": {}, - "type": "text/javascript" + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} } } ], @@ -244,6 +247,238 @@ "url": "localhost:8080/class" }, "response": [] + }, + { + "name": "duplicate class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Class name already exists\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "duplicate attribute", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Attribute creation failed!\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDoubleAttr\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "duplicate operation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Operation creation failed!\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDupOperation\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n },\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "no attribute name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Modelelement without name\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoAttrName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "no operation name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Operation name is required!\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoOperationName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "POST performance", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "// Generate a unique name using an iteration counter and timestamp\r", + "let iter = pm.info.iteration || 0;\r", + "let uniqueName = `Class-${iter}-${Date.now()}`;\r", + "\r", + "pm.environment.set(\"uniqueName\", uniqueName);\r", + "\r", + "console.log(\"Generated unique name: \" + uniqueName);" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response time is below 20ms\", function () {\r", + " pm.expect(pm.response.responseTime).to.be.below(20);\r", + "});\r", + "\r", + "pm.test(\"Response time is below 100ms\", function () {\r", + " pm.expect(pm.response.responseTime).to.be.below(100);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"{{uniqueName}}\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] } ] } \ No newline at end of file diff --git a/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class b/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class index 721065c02b6ce3340f1ac9fde2c6aec47f7c4466..0498f7dcc2007c9f0f13368f9d4f1de3e682395f 100644 GIT binary patch delta 458 zcmYjN%}N4c6g}UJqcCcqs8qC2$uh0R(ta(=tTbpB6fFl5G0cS{kt-i!UL+wh3#w&A z?R$e>AzDahMhQ3foO3zfJ@>{;ktfR z4(qi>S-)t7%Qsb{X{d-H;emprKrnuMsbA|_O|Mt9lV+n@uVm*=-I&CJ2aC{5Q_eV- zJXl8B{FJ}VFGoq_&4}{WMg(J!m@Qa+@DnpsPT~qtCMvdCrP8PbQAuR+ zW}VeDFkl0lR03IcBv_AI9A*Wjk`Hj5CGOx&-oyNGx!c|+#LoS*UCh1M?H=YOydrQ* zw`?c);UEuil_16uLX_1?3k@a?(>NPj*k)?Zekr2ZA#u{Q%g++nLz>)LCPQT{tunCa e?I9&#rH$S*HFA$SOeol%efkb;cKH8UMc@zE7d~zP delta 1156 zcmaJ=+fEZv6kTU(J9QXQ3JCR~sR+o`0^*Gd3RP}$(*hOoc7y?jPG_3Vfyh%oVjlD- zOoSM2ChDW{GkozEj3&fA(&)~|#qTQR$I;;z0E5VGD@QDU7R|US zqeVq4+88dZ^GzNzxVaijZrMW1F!-zu!B9Kl?dVo)Ca0SsDRLUm#DnNyP;@(*&1tq~ z3I*2?lhLK38$Arwr_3KvS@SRT*opHJzdH_zmgirj^!W z1^)%N!+c3txh;nGr9O+m!das;+*~#^yK%y@(i_=$xzv)*iOJcmtab`~(fPo_dG8e# z;R$XSNnL1h26fCdwVY>4vt<|zO=Sj(x=zTFLElH@|4@cN!2>QMUkQmm07h#SLKGiS z6`(jl(MQqmRg+Z3sA3fTZF^wblt`GO)dd5Un5I=N05F5cR53iEjs$mjm&kk+=i2un zr`kT@T>CDn58!n8gZZ8vG=-?{Jnn}j?Bn_*ZFC&sjyvD^8T|{PdwUrC>cI|>knjyP zABolHDTzR)yoMy#q8=9!MIHU0>d}udMiB87MhV+Zdr8cC#^*?D-W5yI=r>QIQVQ^KH-bX{peJI8Icklaa diff --git a/use-api/target/classes/postman_collection/use-webapi.postman_collection.json b/use-api/target/classes/postman_collection/use-webapi.postman_collection.json index 246729bbb..3555d7aa3 100644 --- a/use-api/target/classes/postman_collection/use-webapi.postman_collection.json +++ b/use-api/target/classes/postman_collection/use-webapi.postman_collection.json @@ -224,8 +224,11 @@ { "listen": "prerequest", "script": { - "packages": {}, - "type": "text/javascript" + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} } } ], @@ -244,6 +247,238 @@ "url": "localhost:8080/class" }, "response": [] + }, + { + "name": "duplicate class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Class name already exists\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "duplicate attribute", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Attribute creation failed!\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDoubleAttr\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "duplicate operation", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Operation creation failed!\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDupOperation\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n },\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "no attribute name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Modelelement without name\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoAttrName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "no operation name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {\r", + " pm.response.to.have.status(400);\r", + "});\r", + "\r", + "pm.test(\"Body is correct\", function () {\r", + " pm.response.to.have.body(\"Operation name is required!\");\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoOperationName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] + }, + { + "name": "POST performance", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "// Generate a unique name using an iteration counter and timestamp\r", + "let iter = pm.info.iteration || 0;\r", + "let uniqueName = `Class-${iter}-${Date.now()}`;\r", + "\r", + "pm.environment.set(\"uniqueName\", uniqueName);\r", + "\r", + "console.log(\"Generated unique name: \" + uniqueName);" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response time is below 20ms\", function () {\r", + " pm.expect(pm.response.responseTime).to.be.below(20);\r", + "});\r", + "\r", + "pm.test(\"Response time is below 100ms\", function () {\r", + " pm.expect(pm.response.responseTime).to.be.below(100);\r", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "\r\n {\r\n \"name_mclass\": \"{{uniqueName}}\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/class" + }, + "response": [] } ] } \ No newline at end of file diff --git a/use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream b/use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream new file mode 100644 index 000000000..233bdad5d --- /dev/null +++ b/use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-12-10T09:19:20.103 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream b/use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream new file mode 100644 index 000000000..f29696b82 --- /dev/null +++ b/use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-12-10T09:22:32.307 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream b/use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream new file mode 100644 index 000000000..f5a07f726 --- /dev/null +++ b/use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream @@ -0,0 +1,5 @@ +# Created at 2024-12-10T09:23:54.605 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + From af175c7ee67076eed2036f7bcd2993686466d34f Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 20 Jan 2025 08:25:07 +0100 Subject: [PATCH 007/148] removed maven build for test --- use-api/pom.xml | 125 +++++++++++++----- .../tzi/use/rest/services/MClassRService.java | 1 + .../src/main/resources/application.properties | 1 + use-api/target/classes/application.properties | 1 + .../use/rest/services/MClassRService.class | Bin 1530 -> 1530 bytes use-api/target/maven-archiver/pom.properties | 3 + .../2024-12-10T10-03-05_575.dumpstream | 5 + .../2025-01-10T08-46-29_140.dumpstream | 5 + .../2025-01-10T08-47-48_006.dumpstream | 5 + .../2025-01-10T08-48-02_892.dumpstream | 5 + .../2025-01-10T08-52-59_013.dumpstream | 5 + .../2025-01-10T08-56-47_646.dumpstream | 5 + .../2025-01-10T08-58-18_068.dumpstream | 5 + .../2025-01-10T09-01-27_366.dumpstream | 5 + .../2025-01-10T09-02-25_889.dumpstream | 5 + .../2025-01-10T09-05-40_494.dumpstream | 5 + .../2025-01-10T09-07-36_412.dumpstream | 5 + .../2025-01-10T09-08-55_874.dumpstream | 5 + .../2025-01-10T09-38-00_165.dumpstream | 5 + .../2025-01-10T09-43-38_861.dumpstream | 5 + .../2025-01-10T09-46-07_297.dumpstream | 5 + .../2025-01-10T09-51-10_421.dumpstream | 5 + .../2025-01-10T09-52-19_038.dumpstream | 5 + .../2025-01-10T09-53-49_116.dumpstream | 5 + .../2025-01-10T09-54-45_572.dumpstream | 5 + use-api/target/use-api-7.1.1.jar | Bin 0 -> 16808 bytes 26 files changed, 195 insertions(+), 31 deletions(-) create mode 100644 use-api/target/maven-archiver/pom.properties create mode 100644 use-api/target/surefire-reports/2024-12-10T10-03-05_575.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream create mode 100644 use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream create mode 100644 use-api/target/use-api-7.1.1.jar diff --git a/use-api/pom.xml b/use-api/pom.xml index 1d8d953c4..c727dd75d 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -108,35 +108,98 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.codehaus.mojo - exec-maven-plugin - 3.0.0 - - - run-newman-tests - test - - exec - - - newman - - run - ${project.basedir}/src/main/resources/postman_collection/use-webapi.postman_collection.json - --reporters - cli - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java index 38e58fa92..dd75f8eae 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java @@ -19,6 +19,7 @@ public class MClassRService { public UseClass saveMClass(UseClass aUseClass) throws MInvalidModelException, UseApiException { MClassFacade.createMClass(aUseClass); if(classRepository.findById(aUseClass.getName_mclass()).isPresent()) { + // TODO Exception already exists throw new UseApiException("Class name already exists"); } return classRepository.save(aUseClass); diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index 0cbfab18c..dd694a400 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -4,6 +4,7 @@ spring.graphql.graphiql.enabled=true spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.main.allow-bean-definition-overriding=true +server.port=8080 # /api-docs endpoint custom path springdoc.api-docs.path=/docs diff --git a/use-api/target/classes/application.properties b/use-api/target/classes/application.properties index 0cbfab18c..dd694a400 100644 --- a/use-api/target/classes/application.properties +++ b/use-api/target/classes/application.properties @@ -4,6 +4,7 @@ spring.graphql.graphiql.enabled=true spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.main.allow-bean-definition-overriding=true +server.port=8080 # /api-docs endpoint custom path springdoc.api-docs.path=/docs diff --git a/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class b/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class index 0498f7dcc2007c9f0f13368f9d4f1de3e682395f..263915a67031a004dfc2628aeb5f68f26748a465 100644 GIT binary patch delta 23 ecmeyx{fm1;3M;EPgA#+}-Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream new file mode 100644 index 000000000..61720b4d2 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T08:46:29.277 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream new file mode 100644 index 000000000..b5922a932 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T08:47:48.181 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream new file mode 100644 index 000000000..40c400aa9 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T08:48:03.042 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream new file mode 100644 index 000000000..edd9b2991 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T08:52:59.172 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream new file mode 100644 index 000000000..f54579bb4 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T08:56:47.796 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream new file mode 100644 index 000000000..0424e9184 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T08:58:18.240 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream new file mode 100644 index 000000000..f9a0cf840 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:01:27.525 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream new file mode 100644 index 000000000..9504a75e7 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:02:26.046 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream new file mode 100644 index 000000000..1ff5af6be --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:05:40.653 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream new file mode 100644 index 000000000..04266e8b2 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:07:36.581 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream new file mode 100644 index 000000000..87fe53c9c --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:08:56.044 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream new file mode 100644 index 000000000..951334452 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:38:00.321 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream new file mode 100644 index 000000000..af1297e3a --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:43:39.012 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream new file mode 100644 index 000000000..08ab587bc --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:46:07.443 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream new file mode 100644 index 000000000..c5b5f36f2 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:51:10.574 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream new file mode 100644 index 000000000..962055196 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:52:19.189 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream new file mode 100644 index 000000000..9aa6678a2 --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:53:49.266 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream new file mode 100644 index 000000000..0eb9194fa --- /dev/null +++ b/use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream @@ -0,0 +1,5 @@ +# Created at 2025-01-10T09:54:45.713 +Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' +Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true +'other' has different root + diff --git a/use-api/target/use-api-7.1.1.jar b/use-api/target/use-api-7.1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..d3970f06689070697c7342c8c26dbb4dc73c6e9f GIT binary patch literal 16808 zcmb8W1zeTg(mqV*MnD=tx;q3UrMtV?bayD78)<2fl9rV2?oMe*0YRjt>)Ra9bL8Ri zobUbL{D2L6=9+cSUNdXmYvxjrhK50cfIxtNn31E^f_QKtf?vyust7Vj%84;4fWW^pdjUE`?P}2eS0i!^#Ja040Pz8rjhyW#(x%xB>^-;UUTK6RG}b6h;Zz8YO1d z^^LU+D2V$Z{2FN`vXUm)>VGcq;33Q$f%fJO*8dvlFR7|WQZQgCJ4dtsA#sm$FX8NN z@j!|kG4yZN01u>GoJ{_QFJ=NKPj6aE(sClg0k3nLS!2gaDu{ywayk5p~! zj7=W8Ll^b$PQ!U5?`UFg=Vak*=lJG<5j2;mzui0fKa`xDABaD8Il-UAjqGfl9qp{G zO&lL+J~o8^C(S>2;aKYLUcdnBf$ziF2575qbZ^AS*}~5DfuYB<92KnapIL4LbT#>3 z!q5IG4E}r>!SjXj?=#`C6|(=W2v%kQ+W(q#zoINjj8-ro?Ty`!DIiKDZHiBnKCpKT{IAm|LDKEQ88X_CG_D|ZXU9ctc?9-Fm5$D2^0GL1LCwW@|GX`ShK6>!A8Nogd2QY*x&wC2?pcbWZB& zFR$aPGP8w{mJcs;@ri|r#v8NPY*o1C1-YcVd`@5}>SpZOYl9<_eP@NjE0Ui3Mf4)G zRI`L%f1tgPS{%%prb-bB;~^RezOilf*w)(#?-_i@W1JCK=iHeZCZo&N{7kiNsa>0s z;hOFnY!CX>kTFGOY2#4F6ktkL!~dM>XON*$sccOG<*Fk8QX@D0*Rk)`$L`by>WgPJ zdjiCX3yU(7?tNQr@;}!T-PLsWi%4@RqRL@jGG%#pYaQV(5Lo37-%57ZoP6CraCI++ z@9!4HBd*!P`JKinpD1Yx%1zch0Xx_p?BM(GF}5?ZGI3-uvaoi5`d!P@IXYLs;6G5B**v%FbAkeWT9jVVp=!j;A2$e5`_?n+irb| zkIO4Y&+FK?jq!|`wd#PKycFXO{v_l#P1e->qTP$AfTuIA{p|+MX-RKJmnN6ACqrx< zzZb>0c3CEhbi}GV5KWdPN^Y4VJDq95!vGqCsWlgVG%&B@5z#0JRt??0W=6dI8_m@yZjFM=ho zZ-Q*s)`>~i$VHVr#(ia_V*#SqZYe1_vOI6A@ZLM^zX|Mo`Hc#>1V%Pw8{goGi=C9l z-J-sb)fism-WP`ab>R@6zAjAzTE+GfA@81%y!h|sN6&!nDjESC3kZ&_#m~%xqN^PT zjbK>dmEk1cugjRdj7$v|3ux!SMm<|ob^n?AfUhF zdW2dDck10V3tSpd^0kX{OZjlyH`B#Rt%$_PZKwUVQitU)8ZPw9J{5$APUzaM+J45k zP9>CgMViW_AkSP3H*NPCZKgsA{jEOY!FM&}h(&(uIVlm&&=x$V-KQoWlV@1aEkm)- z=q-?EMwR`Px$_)CNGL?t6M)$Y^#&8&7n7QW#ECARL7!+OI**~5#8 znJ+hJy~k6mOeGww#3DitHtwXXdai>@ z58Bpi{iJQPJcq*g%<#-@Fnc`yOE%Z-g=kvv1{G8RaWehSZ z(Pg_O0X&^)${ojMhRi8T1rl~)ZAFJKv>|!N7ZSAx@N|o0_Xb^7rBMV}=sksuwlAv^ zHBO_^CK7XqUX06UcG;I$A!70HqrPqr{ zBye7y*Kb^Zrk}X-61va1)Z;X$47wHXl$yUDus8Y;%C3TII--_qD>_goi_9k|%^cEn zIgA#seh10yDeVk3^EP8^%`9`=19zt1Fp~V!+h296D zHH-H>H$En8j*uW)&V~q#3mp`a5|so0PVV9zpDZUAuCHnxp5P4FIwZ#n;P(rBtE}@X zG90@e+~(kr{KHreX1QW7P!DbiT6Bkebg zP8CB6j3ktp3s`6mW*rDkQ~SyeQL8EoaU&PUp6CC-$Pe#@XNi1w?PrYPm9`G&=9qZy zLE=Ir0Q&ay`Pj=~V_t{m<7pln)NPgPPwNyxq~1NO-tDpWav0>A9o#NO;byaK8+VX@ z5AM}E8e&dxa0|ghK(PG31^2IjPE)axe8lMITAG5}}`vJ>zEH+ren*#j9NOeHT z5-xl%QRF&{InSN=+!m;tT9cDnEZrEiScX+zC4buXUHd9B%R4M zsX|zwIBJjeJ7q>jZDUO2?&|Q49A6e47Ochr`&!T0cER@nuDK>v&3kKBad?i1`uX2= z_NfL!^-Bo!4C~bR8(ibD52q#dLD3*U_c6N$`ggOIHDof$&zs(1bQV9-x>NOH$=j{J z;x;HVzl>L1Dzsrwr9Oji&XHtWqcZl^bQLaD79H91L}On*f9Gmu29t!e`3#34L6T7nLDS>@6Q0ERb{a4xNpj&A=U? z_P8%0am-7{b;g}=#k2en)$ediB4hd*w{!OKsr$?ouNTpny$mffd;e-?u9q z5XZcwbY%_UBWXwBq#}8xUFHPrED7SuMe&QPvdXs+qL!==pCPL>@L=#D6wIJiEj&lQ z_HUWM$;L!HoJiz9DG-1oSs9ww>opBn3r?GJ5?FTgJYBB!X@x0+z!F3iA^`g7{bT_M zywjeb?o(RQ=;v2R7#!oYOSC>?6{e2X`L<<->q7gc^Ja>}Qq`od!sg4z!m3#1pr8su zNO5X^YM9;+ZTtY1F1LA{>daFO`aa8epuS!`o~DXhn3^zijKuq0TD8Sc-GO}P*&8Sp z&knR|TB!zxySc95>1UEoW&>K~2AE-D^T!g~Yflgex=28RQY|Yn$~Bv`NZ3{zrS-1u z%)5mtp=$_h1ldqVxcQDeQ-GVABH9TTS^zvxQ(}r^D6^jtK`*S_it@l=CL(kzQxV=t z--*J~*z*kJ)Giv3eLsd<*2D^Bck~a#Y`@ZFB~0a{%_MZLk`S&6I$CbjXf#2nN+`3c za&vStn)hm{7+jyQQZcQf2Bn;ig4z=6`j|hjbjc6dv-u`AOZXQYLwo!jM$FOrSrYdG zRHIzz=!x|fWQX3)+k$DKaw%}p(i1T+{RNt~wv76!q-mAuOjS)}O_9k%k|QaQcPb2b z&hnUlEY(`Tt!>&uDzl?TcxxZCCNjI-X}iTQ=NjX_+ZDt^Wwx1=t&w}SO1!{9Syg0Q z*-#$!EoyrHSrL!rjL@WF*zm_}B27B>h@#S}=Xoaeh?eW~WYX~|*>9qNq{PS+2PIq; zfc_7F!CVH-GABLBmX{P7E|yr*40GHIw`tC4)5n2d&m(IZZ%=%;Z{*}-mjK*&Y0a^t z?YBptE!sJ)3C<)k+o@xox%$?4*T1WjzaTSc)6%)?Nc|HP z+x@3Yc_hW|_3}DfA;tQXPt121(71d?2(B1&7_>$Q3H>D8C|Tq(OQ-gImw8;2dPbKha7}}n zUk(+1wChS7Rq`4;?LS&Xb8f{)CBe@I+u(y2l1JhD>u^HQ+1b&;(8c+$2v+v7!VpAD zlbuMH92GIrUYNK1I?8UTu9AaB6Zn=m4%-^#Jkgrb>I;V(&K^goH!ZB_0jhv6k(6hn z8)ePQB7&izz2THIQ`^1XQM=`kkD{DmaoJ76u!*MT3FEoU-<@s*4;AU_iB8vjYpWtv z+;S+g4T(K3q*nYDUA`$aVR;h!^Dm2wjoH1|GSi`bF9dtzO)bqXUMg&+ORF3-UXN(_ z$%C42*!;8{DQ?L$?vtG}E`tCOtky+Ew&4_EpBh@AmN^z2OEv}C^AHJS{y4>ALk4L1 zBeP~ovRbB-J&}1&FC#4i^6GKa?14z6^}W9Rfvs1*T~$xr4ad-ES9ysNvpy>Sozom2IK~G?(%?I?ne#qp51X|3Rh4A1WT;S z3)!s?zTzwZxg>XDZyp$2ARzn49)89m#3(wpbn_`D=8soHB2KybhP$Q7dW?`SG${Y@*=5s>; zvLh2Zau&R)$ai`5s8=7`h@Wb&e!wtDCiYSEN7=R|0ZN#Z#CJ_Wg8>5pobP3q)zI-z6YQYoXO)JYzdAkaKAdHvMnD9iCM0T&fk-s(Z z+xDb@kIxNUS;T_LIo`t#aOQgHejoobQQs?(fiv7A-Q|lR1v{dU zDF3sdnXmAQADZ-}CuP(WrU@>DX$X*&KgQV?_|sYf62;%%>_u0Rf!5eI3e3ZRS>@Bf zx?9sN(SdkEtU_CTTaR=iyt#M4NSG*5G(+|e-Xt)4$}KV^^-V2b7s+*X%A3$7%N^ev=8pAqx!ack%j7x);r*&Z>L|vH5!7t z_fde+9>VwL9S^?cZN~-Fw`u^mxDNgE)3JEH&m9c-el+-n1bpo9AEM-_2tOrhzh?@K zbuRr%TQcdqhKbiLbj&lW9?KEy>#OPRE0yYNm6R>vtM*xj!2J`i5QaV@g^hotoWoPlwX?=BQ+ovIJd zOz!8R3clZ~UhtMi4t#1r{KuTA>SXe-!-8L%ns_xECk$0gZ(Ah<*-0GXf(cR>6^Voz zI%;&;kU-*axg4?*moC(y;k_61#%HFdu=%%WKK>adVjxAcYsg#bUZ;Iqjs#*?4n-P7-%F*WZdW_4+87t~CHj1IFK81A>8`o@wce_f~&w}KZe{czYWRRv9 zvXXv@#*a$44J%4-Sm0YLMg5h&K7!QREd!a(n5%i?wcM<6pSqO?Y^o6#kH75&|FZhI zD7}%zll>J>$Rdj3RjAGmL8QPoo0L_ZYPRROiXI*Iw+`z;k#wi2ZQG}!gU80WvBn== z<7C=jQQTz9XI+!u;N%Sp+a7%$xt_3P9@^vLiwcfr!X0A4s^JcvvPDs~V(-6t`le}x ze>Fw~vL0dd>1GX;>&DEN1*$OrZs@RuK<_tMHaz@Gi$n+&BemRwpf}s7=??ql_8Zbm zqsnB=paGGyPdQ(!O#~eIj?xuR^5b+CQRNA*jA?982aA-own7dRYoZd0syov}+UJ!_ zs%IT|52+m+JC-+8;HTUs)^7Orcr4SbM*>F)IvSWsuFHH>e;Cl8`mIrAT6yH4MO&L( z*7B}%eK!C-3+BkjQGv{NhoS1``nXbpnA1BK@kv#Q4n8P5Qlbkv4_a>UhYw}umbHAS zyH1=D3)Wg=Z-YEP5y_Zv6&cy`Q&a+qf$K6m4lHTVg81?qb$31sH(BXRm_c}GR+fEf zI>#U!4*TS#2GIuNH~8Dpu;`ib_)HT?%A*usOxtfnGjwy3j~b4kliEC96A|&YtLl&? zTKeLr4Vig{V_c+W_PZ2Mx&;)=;^Rf+hcCB#Pco+<(ySm6Lg&sx5UqjSN$fF*C`M!} zMrf?QURsr@7q}_z>rrG_;R7jZq|iRo%Vn$@eaWhHAPsUL?SUb67;%}uGA8Z&!qqoS zCTKgUhnGP~+^Xbfs-o}}1v|X8?E2U zx<)(55Gr~01m&6}#w*^SVVtf_!Ms{pnlPz(?VsP?iCl}ZK}<(Rav`ZrTks9RcqCb* zR+B44b}245ZWG!B3Qwy_yKiDWQ%Y(N? z>A4K~zW&s-{*Jdomg_ZJ$bv@mm_d{{#40Jc8K_;o`^2Fo&*R}CH=f2;@4ItE2$YXaA%$teW+h`_USV*qJA%RDkAjZi;AwC0S9Kx{)T4P2|RZ0+o51u zQ;T4W)oT`w8ZRIMeb8OW`TI5%?G5hDeNn~D4D*%stPhobZRuq z2l=2+*a6^#*na4);$hJE#V@AfWEv0@p3U{UXP79K#<-?3OkUyLKF9$LTTkTh&d|(zPmFueidurb8Om6JG?* zKhG}+qJymR!(Q3@y=95637hIinDWi7Yt-z>)>*sIv4<-2`7URqkJnhOxlr6Ld~iTo z7rYXt4!NuP(|i?LCEW-92t|O>0BP44lChJ0J{cWy#!B?s9cTu8G9w(m_{y&331_t9 zU>npI4tw~$X(0Nc2V8=|T$|Tx0|VG=ZX}v9@q^hmjMtZV5`=2#oyBHPw6CE5eya6( z)`oo$Jl~YTB@fC+^X@_Q?_bN061W=pYx?END_VBELi0+|%Ek^AKY&StF2COia(pf-3dX8VUbz;(?Bg-Rt8C+A;b z`R~%@FW;1?+9)fFV|ph*B$DG~hN@_5V*6`i+f@XF9DtGXtMQMOgrhQu>7yAPw$HtX{M=?57+tWq7vmz=$G!ayv2qU{a-~ zr{}Z)UirW#iDPTwO>R0s=Sk`}F-6J1#tKqg(=-eSMJuK?*laE99Y%6{NHT0O8_&Qn zz_uO=-jDYRnxk~<1X`wbNh4g819>se-HdY(JOGId;S1-u>bR!tuAdQd^*!(!T*`3* zd9LG?PzaUC4#=X<;#KT$FZ~HY;uhbytdQ~Y#Q_*IR2=->FF+#ed!Y$e0MtqGz5;mF z)x%+lq}@|UGwYtimz4B6wGPm+0A;hwqdY(>*`#g)MX`Q{ zx73bSaognqpYa8xq%v&!>TJG7nv&M1>Ryy5`IIL!*=U^m1GBCaYDr!Mt5oWWI~db@ zcH3{G)mfb}vI5k@WCu)it@|Ys_@Ym4e6zB>3{Tn%*yDnB#IJL;6$Q^hjfBwYHiZWA zpsa?ru}^bAT!$Q{bj}?UblW-@d8{8WSThTb!Uf-UyS-1OCf-~di>J-RILj!pnSU31 zccasAHevEM(Rest1hn4fx}Ol%i*J9}WT=-#)Y+_DekPKfn5(~=XCL3;@C+r*9Rx|6 zLHUxiiw+)rK3<`&aMHAhuS(O-7_hTf@;r%EhX*yuFIwA4Zd6nrn=|$9quNCMk5r|6 zZsom9qt4Hs@r0xWy4(wQsIXyF`w(gM7wK%Z&qZ_#o>}LH1CPu-N*eJ+LJlM{PQ0ZQ zuRrH-Xgn$8wg^!g1JJFNe-;VP*oxxe&Z%rTcm65iQjMeACj7Gl>ZjTkRqQ(NFr4HP z6&~4315^FU@K|GVc+=&88>s+(UUNF=>~m0yt288Pxxp)(!?&-h4m}sRUS2&b_5$2R zO4~&V>TLT<)Q}{EkJR=QAy*v}-c&9apeI$0NJO3*3!wWj zRQ}x}2Sv~micy}pVqn@dz3flqY!&upC93>qZLNRLAaV4gE)?JlatR9o!T6^P@~8l) z^zQ=Tzt?pYZ6^#)%-eOYIpaArW<=S#_x6>s*tr{81QYnezR53`aVKb)!YkBt+TCX= zW1u%P4w$xN;NQFEZ6p(Q+gB~Y2ooQa#Y8$YF1s;aoh}O8L4I7z3nKs#tn&ek0)eAO z<&3YXv#?t$FE!vmKx0MG0eTid`~V%J7|UkcNg49h4iqA9H0tBru)>GCEuQ5H&A&XIPn>GIki+mInHpAF`X0By@ii;#6y_9CJ`9e z_}1u&DIY;EBB;X^3&fJUuQXt6JmJXiY#+M1Mf`kRF+smNyHo(#*pe&sX{StRDK7e4 z7D7SQu%05n^1L|?6^q$|Svs(=D$VOn_t9N@C!Rg1342E+Sy|uo#cLA=pPvU9BdlB; zR8#LXFr@+z4-iFyAeMH-#Hu$!CoEsYO;LwNlpPe%CQcOYM0QsupatbS90h)oLbqt4 z^k=^^9Q0Lhr1UO)I!9i6p=I6prb9itY0>7>zh<#VQF?c(F4* zm%xugcfyieqj!8ojbDg`I4Rq=+fif8v=?aA&uZDVNd9hcpkw}wWtD9j$K}L~E-OOD z*xH@2pYu4ti2df}r8$x`g_Ax3<0?H2F#KR>12^ z+u6&e_VqzbP=xZU^l8Z>{veA>k0C?Ki2Bxj&M*u4usWgg#7h{{Lun+|V10`?+|o5` zxNV)D-fBqBvbKXG45eUriF!?6twN`WmYr>jH*`jvzGr_AxF5Kr=-c3clL0T;WRC(4 z{NOC8ASw8uN9JFLIcaJ(ZWyAN-g&Z(+Z@%vOg|+(D?joodNmOW4I5~Q7hdIv?V;`? zd(nbh%%kwzLNy1}*G@->zDoYo7IMeU|TF+yDY5fPrb z@Y&XmGYotoyDEGZ>a;2`yqq?J7^8g6*4m9?gKn=oG0V|56m%x2uZl%p`vckZL#Wo@ zM(*OL?=~SA*^OVmH4wyS+1G9{LCnutA@7v=Vz#h^p4ajN{Rp%l!k&k#gk3NBm0gu< zNFoSiF&A73m^r#Zq>A&sbYNupEGEtcnZwS=9KK+eaN!?{rxT;d$Ru7t{WXGV`vfmVN;lLNO=EuQ$j| z^#rTk1PX)Fj??u#HIUUUHq$j+*|Au-;z!kWO&Kre$AH^N4(BVtI)-YA^r`XU^Jd&Q zSA{iEkQ3s2I|TXA?>FCM#}TCpR;0gcf3ng=v{1EKwg`m>q3vSnk(p7PHWAF4tejX3r{Q8n6Y7mWdQGV5xq_AQ# z&Jf>4Ynz?zy?7|RLF;%Yn(YJ^zO~#6G(KA<6!sy>uu)x56zSK690n5$S(@9(@?JiV z7YH1Zf|V>p78U1Q5Qm6z??68lNkcxXmbQ|6U0)I*hA7vN0s zhn~RuraLziLvY_6<3HbJv~;qw-PN|STi^oRez`_Ub9hClv%_UOR!zt8q1FZZ$*gOg zOGZMLvUTpEsdPGhK10Rz8QDf{)6}qZEu)3bhX~{7Eb1c?ioAgN$kpRg=JZ%W8?)ZJ zaFJr60VXfhhVZ;aZficP`Kw4L=elL?*RD-I&Od5S8*6q51bDbkBO3{gP!V6E;3<)_ zEVP;u;$K+!{5aK+IFywyp!Qxe&*7WKQl8UEpzG+F(KrCn`TN!n1V?%GRxo(v^md@r zj7qy=AQmJI9$rb~5 zrqC+o;B1mB;iRBY6{NAn{d}!(_|j7M zjs&F!u0{;bbG77dCtNHcnKH2je>;t*>yuQ(QwqrMtb|wS zn_ty)%fF4Z6g^hOV~td*gF%*xVQbiZ(t(mQGpCI~94Q?} zu-bPA7K=s(ZSgRyJj-N(4hTCYZ`7^fQLH#{$oYc;X$6Ufq?m~c1|Q~tdl(a!vYeDK z4+}A`I+>UQx=qPV7hZdRY}T!Rq4HRt2t&Qn$xM^yj>+h)kb>ODxSy_!lEjs;t<2&k z9TBWME^#HD^aI1X!?tds{W|SfCvRjf*$?=RXiT}EKOMh7dfIg+jSOfzbY!`Mr0GXy zWjL4YW)%)nGq2)!mu z2uRr>n3Tp z^kBCQemir1XIJ4)YJ<7zcDxLq!p-z(khk@gX z;8fchayPn`0y~X4|$c$jQ9lh$Aibqb1wFrb|FY*=J%EGj*D!CE^UA#SvL* zH=nAGe!DD#u2;&bB9VkZtNBr%Uxt-LqHhokyEbn=f?>g!Ok9~rW!beB!Rw7JZdUuKWPO9JnLuN` zJ}+&j^A0vWAnB}kGALn&)GzQzP3{v>UY8=w+?v(smWRyQpIhQjabp5GboJAGcEWcqba*c zvYqYoAgP+jR`>KQCQWC)b&s_{sEjV!)7G^u|o znk~4*8aZzk7!!EaM&i;>4od5ciTV^u79_!?)$y@DXSTJ9A_8)%IC>DO9UVN00V5C8B?$GT>Ko|{VOH=A@brR6216T^uhr( zta%{1Jj@VM7nXgW>emQMxZ$Yl7d`ulpFbp^5-XqZ>ROOR5{?|owu$bzjT9~y65v!= z++otBRQj)oi6^&zsG421f2Qp{Z*p6ce)LiMU_tbJeniyfT;TV@HV&>JS>%LF3xS_E zJBcA6Xu%8Hqu%w0?dX4XmD}6dFuu02-q6&xTj0R-Mtyhp0nY==glAX@CN$J~+ZSqB z?ZZx4tzQCeN-4P`ITjD$>9U)MRE_zLP-DHb#`EyE*H7M*5~1cE40B62dytZwTuhn! z_mD-cvq+osx8i$U?wZ}5Y{@#iKXq(RAXj_d=Je);7IimM0CDFTxp>mo*Mevm$19zm zYTN19K_+tYO_%b6I;9kgeI;siRos(LCl6mgy>_^|C8Li9W^5|0@=_)=S}x0GL zJu&89=2t{OsQUr&eW2it#_n^Cgyng6HZ= zEL2`3p~)S=C|#^#e|s%gkydBBX`}w5Z*S;Fx0WMh=oiG)Xe^A3@o<(Y?DHCD)(UT$ zHO}hozVc=Q?f?SrYovAkx?!ZU;V$sx}(f}qtrj=RKN7E;~R z@+>y(=g!Zw@s_k8ztV(Z&H57jTtN#4-%sT*(ReHGLa@*OkO+S~w~8H*S#cULhD%cP1%)4lha1geV^ z0)+wJB}=&4ASC=6t2BHtEVE@7xr+29o9cEjup6yV42V?vGV2e+7H@l=mRLCYGY%wJ zWW0!)Nn<5%Bjiu0KqGe;U+O`%@`@Z;sOD!Uhle-OTvusl%2!Ba%(H-OeQLhV&GW+} zA} zN#wqF&5eP0-lZOa^)v7JuKb@>6>fa6p3565(86S^GA7TJ$~ErCen~nPPCnmQ>TXA& zGc`^3IfP5>Q^T)MLecW|)^H!8O5V)7Ln*xN3-4uHC(tA#55pKl z-u2|>6M8H_u?d71e$Yxk4>wbIv~b}hpftAim6r%NAkl0K9-+;2tghm86(vjnV|9Dm zyLBow>7DJ29cV87xkgcwBx*MhIy?{OYkzm{ZBP!icsPmOOsZr>d48%x85!=p&I0S! zG4obYSkI5=bJdffHm7Jp+3&yLRtD1BlPLBiG_M<$jFIDyouP%6PtUd3;JMYBcqj#Y zo{V&bu=0zEQ4*@N>+2Zpr|rCeAkm})#KwLVVr;6U`XJ0IL6R^_oTjlQ{IUBfduCf@ z94_k2T&egI4fwD(iY?dNT`v+0*zpoAwD@q<>f{oFRMNH3mTWF-f2N&*&QP%`o)tsS4pzzcrzI?0G0#f)QxjycZAm(&_ax;)!MI`MR zmC@|cw{m?;6Quq6I4_W2((z_>@x?cq7a8#bQP?l+4?G<{#n~ucaZ(b$MRtYfqzoZ8 z+v2M))bCcQ%N($uyD@okb?3DhLi%aMNS9}#E&6l|$m zDT(&cRVybE{@`(3s1Fp4;V_&Z@n&Uq;HefZ^ZIB~E{#DuqTmIkiKuCka+N?>LJVP1 z^ggmu&GEYm@lv$>p8})QCu66`MmI|)#}-_d57;BJ60};z?8?)e;0(+K{=RP#{y%2o z-^?9pdfI*&X&J^tnQ{gOxhYxtzV!_$rU51f2&8qK+?{w8lkboeuj>bt!a~`OkFAGK z04IPq^9~JoLf7Bi@ z`W_no69w;I>i;ra2!8n&9ps_bV}95@CGXdDKio0!%X=Ed|I)ap=>59xHIBe9{~}&I z)Ot*-yQl2^y6&}b!S%1dw7_fR-|Risyr=N}))acA`KNn)jBros`;FlIUl9ItQvC2X z{zUQn4fW{})L(?Z-?QUSl)vBl%a8OQlmH(N;xRMto&xwA1QT4xe&|a_aG~sP4t@NQ z-%|pAs|){0{XyOBe+}fGBKRB0>rY63^y;4|gTHaA!8rds4*1(GJtp_vQwVJ8KrsC8K=8P%@PW=>A@_)7_7LPx^sL_?wBT;?hcos+ zfPYbJ|NqEZk4-%$i~KePkNp2+>Q`ClG5q5$_}}mmPyP=7&z|_lSdUwBe`Cpj`Hv61 z^2Y|<$8e83D}Td%22ZJf!aeG~ZVFZ?Hvhet!t|Ad5a~q&RDgCJ~^APY)2e!Wf`@xU7f5^!9DeQkA-##?) zr$^`CCbGc$xBroL|H_vCevp2M`=^cIZ(Mrt{_y{Z`+HlcAPo!7a}W@u;I9>Mp{wG4 IlL_(v0p;i25&!@I literal 0 HcmV?d00001 From 3e7a37a5b599d67106c8d7e706bcf6dc3a11f202 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 08:52:53 +0100 Subject: [PATCH 008/148] Create postmantestci.yml --- .github/workflows/postmantestci.yml | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/postmantestci.yml diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml new file mode 100644 index 000000000..650161ae5 --- /dev/null +++ b/.github/workflows/postmantestci.yml @@ -0,0 +1,53 @@ +name: CI with Postman Tests + +on: push + +jobs: + test: + runs-on: ubuntu-latest + + services: + mongo: + image: mongo:4.4 + ports: + - 27017:27017 + + steps: + # Checkout repository + - name: Checkout code + uses: actions/checkout@v3 + + # Set up JDK + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'adopt' + + # Build the application + - name: Build with Maven + run: mvn --batch-mode --update-snapshots verify + + # Start Spring Boot + - name: Start Spring Boot + run: java -Dspring.profiles.active=test -jar target/your-application.jar & + env: + SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb + + # Wait for Spring Boot to start + - name: Wait for Spring Boot + run: | + for i in {1..10}; do + curl --fail http://localhost:8080/actuator/health && break || sleep 10; + done + + # Run Postman Tests with Newman + - name: Run Postman tests + run: | + npm install -g newman + newman run src/main/resources/postman_collection/use-webapi.postman_collection.json + + + # Cleanup + - name: Stop Spring Boot + run: pkill -f 'java -Dspring.profiles.active=test' From d35a7ee17a0172c47254999264539c5bd7d6148d Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 08:57:48 +0100 Subject: [PATCH 009/148] Update postmantestci.yml --- .github/workflows/postmantestci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index 650161ae5..4f1a36a9a 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -30,7 +30,7 @@ jobs: # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar target/your-application.jar & + run: java -Dspring.profiles.active=test -jar target/use-api-7.1.1.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From 4cebe1b5940e00c81ae20bd2d20d2801562f574f Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:03:04 +0100 Subject: [PATCH 010/148] Update postmantestci.yml --- .github/workflows/postmantestci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index 4f1a36a9a..8aef49b2a 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -27,10 +27,14 @@ jobs: # Build the application - name: Build with Maven run: mvn --batch-mode --update-snapshots verify - + + #List target dir + - name: List target directory + run: ls -l target/ + # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar target/use-api-7.1.1.jar & + run: java -Dspring.profiles.active=test -jar target/use-api-7.1.1-SNAPSHOT.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From a1634eac390796358bb8a10791eb848f3a894b32 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:08:35 +0100 Subject: [PATCH 011/148] Update postmantestci.yml now package --- .github/workflows/postmantestci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index 8aef49b2a..c1c482e3a 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -26,7 +26,7 @@ jobs: # Build the application - name: Build with Maven - run: mvn --batch-mode --update-snapshots verify + run: mvn --batch-mode --update-snapshots clean package verify #List target dir - name: List target directory From f3c2ef8bdf592fc0738da2bf4138b85ad51a0872 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:11:22 +0100 Subject: [PATCH 012/148] Update postmantestci.yml --- .github/workflows/postmantestci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index c1c482e3a..ebacf09d8 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -26,7 +26,7 @@ jobs: # Build the application - name: Build with Maven - run: mvn --batch-mode --update-snapshots clean package verify + run: mvn clean package #List target dir - name: List target directory From 4386571196d379cf9b821fa6649bed24884718f8 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:20:09 +0100 Subject: [PATCH 013/148] Update postmantestci.yml --- .github/workflows/postmantestci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index ebacf09d8..9a46f8044 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -29,8 +29,8 @@ jobs: run: mvn clean package #List target dir - - name: List target directory - run: ls -l target/ + #- name: List target directory + #run: ls -l target/ # Start Spring Boot - name: Start Spring Boot From 50a8d955047751fa96adb1546654edc636f6a691 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 20 Jan 2025 09:26:42 +0100 Subject: [PATCH 014/148] update pomxml --- use-api/pom.xml | 19 ++++++++++-------- .../compile/default-compile/createdFiles.lst | 11 ++++++++++ .../2024-10-18T01-16-43_107.dumpstream | 5 ----- .../2024-10-18T01-17-10_802.dumpstream | 5 ----- .../2024-10-18T08-54-51_699.dumpstream | 5 ----- .../2024-10-18T09-06-30_147.dumpstream | 5 ----- .../2024-10-18T09-07-35_821.dumpstream | 5 ----- .../2024-12-10T09-19-19_942.dumpstream | 5 ----- .../2024-12-10T09-22-32_147.dumpstream | 5 ----- .../2024-12-10T09-23-54_430.dumpstream | 5 ----- .../2024-12-10T10-03-05_575.dumpstream | 5 ----- .../2025-01-10T08-46-29_140.dumpstream | 5 ----- .../2025-01-10T08-47-48_006.dumpstream | 5 ----- .../2025-01-10T08-48-02_892.dumpstream | 5 ----- .../2025-01-10T08-52-59_013.dumpstream | 5 ----- .../2025-01-10T08-56-47_646.dumpstream | 5 ----- .../2025-01-10T08-58-18_068.dumpstream | 5 ----- .../2025-01-10T09-01-27_366.dumpstream | 5 ----- .../2025-01-10T09-02-25_889.dumpstream | 5 ----- .../2025-01-10T09-05-40_494.dumpstream | 5 ----- .../2025-01-10T09-07-36_412.dumpstream | 5 ----- .../2025-01-10T09-08-55_874.dumpstream | 5 ----- .../2025-01-10T09-38-00_165.dumpstream | 5 ----- .../2025-01-10T09-43-38_861.dumpstream | 5 ----- .../2025-01-10T09-46-07_297.dumpstream | 5 ----- .../2025-01-10T09-51-10_421.dumpstream | 5 ----- .../2025-01-10T09-52-19_038.dumpstream | 5 ----- .../2025-01-10T09-53-49_116.dumpstream | 5 ----- .../2025-01-10T09-54-45_572.dumpstream | 5 ----- ...eam => 2025-01-20T09-17-37_242.dumpstream} | 2 +- use-api/target/use-api-7.1.1.jar | Bin 16808 -> 16808 bytes 31 files changed, 23 insertions(+), 144 deletions(-) delete mode 100644 use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream delete mode 100644 use-api/target/surefire-reports/2024-12-10T10-03-05_575.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream delete mode 100644 use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream rename use-api/target/surefire-reports/{2024-10-18T01-08-48_582.dumpstream => 2025-01-20T09-17-37_242.dumpstream} (85%) diff --git a/use-api/pom.xml b/use-api/pom.xml index c727dd75d..9f25dcd1e 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -108,12 +108,15 @@ - - - - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + @@ -200,6 +203,6 @@ - - + + \ No newline at end of file diff --git a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index e69de29bb..34805f48f 100644 --- a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,11 @@ +org\tzi\use\model\UseClass.class +org\tzi\use\OpenApiConfig.class +org\tzi\use\graphql\services\MClassGService.class +org\tzi\use\UseAPIApplication.class +org\tzi\use\rest\controller\RestApiController.class +org\tzi\use\model\Operation.class +org\tzi\use\graphql\services\MClassGService$MClassInput.class +org\tzi\use\MClassFacade.class +org\tzi\use\rest\services\MClassRService.class +org\tzi\use\model\Attribute.class +org\tzi\use\repository\ClassRepo.class diff --git a/use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream b/use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream deleted file mode 100644 index 693429e22..000000000 --- a/use-api/target/surefire-reports/2024-10-18T01-16-43_107.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-10-18T01:16:43.301 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream b/use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream deleted file mode 100644 index b4de26efd..000000000 --- a/use-api/target/surefire-reports/2024-10-18T01-17-10_802.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-10-18T01:17:11.008 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream b/use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream deleted file mode 100644 index c6f4b5187..000000000 --- a/use-api/target/surefire-reports/2024-10-18T08-54-51_699.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-10-18T08:54:51.858 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream b/use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream deleted file mode 100644 index a802f26be..000000000 --- a/use-api/target/surefire-reports/2024-10-18T09-06-30_147.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-10-18T09:06:30.347 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream b/use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream deleted file mode 100644 index f3382bc0f..000000000 --- a/use-api/target/surefire-reports/2024-10-18T09-07-35_821.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-10-18T09:07:35.994 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream b/use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream deleted file mode 100644 index 233bdad5d..000000000 --- a/use-api/target/surefire-reports/2024-12-10T09-19-19_942.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-12-10T09:19:20.103 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream b/use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream deleted file mode 100644 index f29696b82..000000000 --- a/use-api/target/surefire-reports/2024-12-10T09-22-32_147.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-12-10T09:22:32.307 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream b/use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream deleted file mode 100644 index f5a07f726..000000000 --- a/use-api/target/surefire-reports/2024-12-10T09-23-54_430.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-12-10T09:23:54.605 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-12-10T10-03-05_575.dumpstream b/use-api/target/surefire-reports/2024-12-10T10-03-05_575.dumpstream deleted file mode 100644 index 2b27b6684..000000000 --- a/use-api/target/surefire-reports/2024-12-10T10-03-05_575.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2024-12-10T10:03:05.758 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream deleted file mode 100644 index 61720b4d2..000000000 --- a/use-api/target/surefire-reports/2025-01-10T08-46-29_140.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T08:46:29.277 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream deleted file mode 100644 index b5922a932..000000000 --- a/use-api/target/surefire-reports/2025-01-10T08-47-48_006.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T08:47:48.181 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream deleted file mode 100644 index 40c400aa9..000000000 --- a/use-api/target/surefire-reports/2025-01-10T08-48-02_892.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T08:48:03.042 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream deleted file mode 100644 index edd9b2991..000000000 --- a/use-api/target/surefire-reports/2025-01-10T08-52-59_013.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T08:52:59.172 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream deleted file mode 100644 index f54579bb4..000000000 --- a/use-api/target/surefire-reports/2025-01-10T08-56-47_646.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T08:56:47.796 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream b/use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream deleted file mode 100644 index 0424e9184..000000000 --- a/use-api/target/surefire-reports/2025-01-10T08-58-18_068.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T08:58:18.240 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream deleted file mode 100644 index f9a0cf840..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-01-27_366.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:01:27.525 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream deleted file mode 100644 index 9504a75e7..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-02-25_889.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:02:26.046 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream deleted file mode 100644 index 1ff5af6be..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-05-40_494.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:05:40.653 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream deleted file mode 100644 index 04266e8b2..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-07-36_412.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:07:36.581 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream deleted file mode 100644 index 87fe53c9c..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-08-55_874.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:08:56.044 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream deleted file mode 100644 index 951334452..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-38-00_165.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:38:00.321 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream deleted file mode 100644 index af1297e3a..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-43-38_861.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:43:39.012 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream deleted file mode 100644 index 08ab587bc..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-46-07_297.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:46:07.443 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream deleted file mode 100644 index c5b5f36f2..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-51-10_421.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:51:10.574 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream deleted file mode 100644 index 962055196..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-52-19_038.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:52:19.189 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream deleted file mode 100644 index 9aa6678a2..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-53-49_116.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:53:49.266 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream b/use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream deleted file mode 100644 index 0eb9194fa..000000000 --- a/use-api/target/surefire-reports/2025-01-10T09-54-45_572.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-10T09:54:45.713 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream b/use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream similarity index 85% rename from use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream rename to use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream index 0a71e38bc..e9d92f176 100644 --- a/use-api/target/surefire-reports/2024-10-18T01-08-48_582.dumpstream +++ b/use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream @@ -1,4 +1,4 @@ -# Created at 2024-10-18T01:08:48.748 +# Created at 2025-01-20T09:17:37.416 Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true 'other' has different root diff --git a/use-api/target/use-api-7.1.1.jar b/use-api/target/use-api-7.1.1.jar index d3970f06689070697c7342c8c26dbb4dc73c6e9f..640a6763172c9ec5fbf537fbb46872c9cf81ed87 100644 GIT binary patch delta 576 zcmZ3{%($YNkvG7bnT3mifrEj;*vn)huL?7WGHGBj@G^;-xI>A>5JcaT1JjcjA^gc| zjA~$k$pMUdLLe0kNI;fha-pRn56oDQ^yIyaIuH$S84WQs2r^7|v=T+t5XfW((a_Cg z0(Q&f!%Vs$w@v=cqy?rGn9V@+=1At-%*;SbHk-5Gf-pq5n<0!@e0v~_NTF6Hu$qS= zoe)N@I1>w4q)56HBJxU>hY>9DQ_dbDWv!eC*1mX+8aH#HtI6i|hV86iyDiOI!Sq3M z6EOY5+#cdcYYQWYvkNWsAPj2@smXgSBp{rd7EoUaTiQWHLM`1Pj0Ki95XJ*bM+igJ z${NB*v2uej)>*kgtodeT3%1wH+6qh;Tf2ei&3mlH!G4&0%_alnm&uN{F<^RuttXg% yW9tK^t?eLmmz_75f5XlTOsm=lg6T^8I52(7J`zluIcx-lz~omBpC`0*Npn0a=F0g_epuFk=k_fExBP>afJ}2SrYP%V;PhP}+~8L6Bjx zqm?LJ1IWh7flOvBAa#?wnM_zddjX9&%%lr)+vLwoT3}j%*$hN)j%2>g%zO>VFlWC7 zVTf=yLm0F8_COesLaj_-H4jBPA&gvcCKj+rk#s3UZw0&Ipt%W{{$Xwp4zS7A7DnKZnp|k12Vq!SNKM{rApr@l zn-*pehOng_gb`}#&H@gh1(r6D5PD$g2=Te9l{LhO6e~A~$T}+*NLYNcvIW~~W^Dzg zi>=*2^yWR*;$S~azGjmF^2=mL+ZZstz}6E?zp?cJ)7Ewny35WR%)eph1*TQ)1Hp8q ceH@s+WgiKq%^Ws@LSXVMhfr_;I60;P00qvmC;$Ke From 17f3073ffc31fd7bd4549c7a0c3773bdd831af4d Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 20 Jan 2025 09:52:19 +0100 Subject: [PATCH 015/148] mainclass added --- use-api/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/use-api/pom.xml b/use-api/pom.xml index 9f25dcd1e..d492142a7 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -115,6 +115,7 @@ spring-boot-maven-plugin true + org.tzi.use.UseAPIApplication From 094deb3f8b1f1b3a4c8b879576c1d1ef04bb9d22 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:37:26 +0100 Subject: [PATCH 016/148] change the path with use-api/.. --- .github/workflows/postmantestci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index 9a46f8044..5b6da2efa 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -34,7 +34,7 @@ jobs: # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar target/use-api-7.1.1-SNAPSHOT.jar & + run: java -Dspring.profiles.active=test -jar use-api/target/use-api-7.1.1-SNAPSHOT.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From ef58bd044bba2c66cb4a9b4e14428be37f2292de Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:42:29 +0100 Subject: [PATCH 017/148] Update maven.yml ls tests --- .github/workflows/maven.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 054da7ebb..9a0397899 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -19,6 +19,12 @@ jobs: end_time=$(date +%s) build_time=$((end_time - start_time)) echo "BUILD_TIME_SECONDS=$build_time" >> build_output.log + run: mvn --batch-mode --update-snapshots verify + #List target dir + - name: List target directory + run: ls -l use-assembly/target/ + - name: List target directory + run: ls -l use-api/target/ - name: Upload build result run: mkdir staging && cp use-assembly/target/*.zip staging - uses: actions/upload-artifact@v4 From e325db0c974bb3a1892c60d234e128810c912ab7 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:47:42 +0100 Subject: [PATCH 018/148] small changes postmantestci.yml but maybe it could be test and build --- .github/workflows/postmantestci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index 5b6da2efa..b4ee25ae5 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -23,18 +23,19 @@ jobs: with: java-version: '21' distribution: 'adopt' + cache: maven # Build the application - name: Build with Maven - run: mvn clean package + run: mvn --batch-mode --update-snapshots verify #List target dir - #- name: List target directory - #run: ls -l target/ + - name: List target directory + run: ls -l use-api/target/ # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar use-api/target/use-api-7.1.1-SNAPSHOT.jar & + run: java -Dspring.profiles.active=test -jar use-api/target/use-api-7.1.1.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From a806c8101caf7629564aebabdd26c722e73f1b51 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 20 Jan 2025 09:53:08 +0100 Subject: [PATCH 019/148] removed the list tar dir --- .github/workflows/maven.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9a0397899..95167a48e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -20,11 +20,6 @@ jobs: build_time=$((end_time - start_time)) echo "BUILD_TIME_SECONDS=$build_time" >> build_output.log run: mvn --batch-mode --update-snapshots verify - #List target dir - - name: List target directory - run: ls -l use-assembly/target/ - - name: List target directory - run: ls -l use-api/target/ - name: Upload build result run: mkdir staging && cp use-assembly/target/*.zip staging - uses: actions/upload-artifact@v4 From fa35e98e816a667604020600b0ac720739555b0f Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 20 Jan 2025 09:56:16 +0100 Subject: [PATCH 020/148] Update pom.xml --- use-api/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/use-api/pom.xml b/use-api/pom.xml index d492142a7..97598e673 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -117,6 +117,13 @@ true org.tzi.use.UseAPIApplication + + + + repackage + + + From 6ae8bcbfcbcb0aca0156de7785425ad6fc8010f7 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Mon, 20 Jan 2025 10:00:50 +0100 Subject: [PATCH 021/148] Update postmantestci.yml --- .github/workflows/postmantestci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml index b4ee25ae5..71b3681f9 100644 --- a/.github/workflows/postmantestci.yml +++ b/.github/workflows/postmantestci.yml @@ -42,7 +42,7 @@ jobs: # Wait for Spring Boot to start - name: Wait for Spring Boot run: | - for i in {1..10}; do + for i in {1..4}; do curl --fail http://localhost:8080/actuator/health && break || sleep 10; done @@ -50,7 +50,7 @@ jobs: - name: Run Postman tests run: | npm install -g newman - newman run src/main/resources/postman_collection/use-webapi.postman_collection.json + newman run use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json # Cleanup From 72b22b0a0ae332f29904ec0aaf9c93edf1bde5e5 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:22:28 +0100 Subject: [PATCH 022/148] Update maven.yml added test job with artifact upload and download --- .github/workflows/maven.yml | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 95167a48e..5c3f6c201 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -20,7 +20,7 @@ jobs: build_time=$((end_time - start_time)) echo "BUILD_TIME_SECONDS=$build_time" >> build_output.log run: mvn --batch-mode --update-snapshots verify - - name: Upload build result + - name: Upload build result use-assembly run: mkdir staging && cp use-assembly/target/*.zip staging - uses: actions/upload-artifact@v4 with: @@ -36,3 +36,68 @@ jobs: path: | docs/archunit-results/cycles-current-failure-report.txt docs/archunit-results/layers-current-failure-report.txt + + - name: Upload build result use-api + run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase + - uses: actions/upload-artifact@v4 + with: + name: Constructed use-api + path: testphase + + test: + runs-on: ubuntu-latest + + services: + mongo: + image: mongo:4.4 + ports: + - 27017:27017 + + steps: + # Checkout repository + - name: Checkout code + uses: actions/checkout@v3 + + # Set up JDK + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'adopt' + cache: maven + + - name: Download Artifact use-api + uses: actions/download-artifact@v4 + with: + name: Constructed use-api + # Build the application + - name: Build with Maven + run: mvn --batch-mode --update-snapshots verify + + #List target dir + - name: List target directory + run: ls -l use-api/target/ + + # Start Spring Boot + - name: Start Spring Boot + run: java -Dspring.profiles.active=test -jar testphase/use-api-7.1.1.jar & + env: + SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb + + # Wait for Spring Boot to start + - name: Wait for Spring Boot + run: | + for i in {1..4}; do + curl --fail http://localhost:8080/actuator/health && break || sleep 10; + done + + # Run Postman Tests with Newman + - name: Run Postman tests + run: | + npm install -g newman + newman run use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json + + + # Cleanup + - name: Stop Spring Boot + run: pkill -f 'java -Dspring.profiles.active=test' From 3891c13ecd83685310199f8e51dfa58e616ac133 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:25:01 +0100 Subject: [PATCH 023/148] Update maven.yml needs added for the job to wait --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 5c3f6c201..38988e157 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -45,6 +45,7 @@ jobs: path: testphase test: + needs: build runs-on: ubuntu-latest services: From bd0b97bf72f05112c3c66a9d6a502f38f851ed30 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:29:35 +0100 Subject: [PATCH 024/148] Update maven.yml removed mavn build and ls on testphase because cannot access right now --- .github/workflows/maven.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 38988e157..a873e7ef9 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -57,7 +57,7 @@ jobs: steps: # Checkout repository - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact # Set up JDK - name: Set up Java @@ -71,13 +71,10 @@ jobs: uses: actions/download-artifact@v4 with: name: Constructed use-api - # Build the application - - name: Build with Maven - run: mvn --batch-mode --update-snapshots verify #List target dir - name: List target directory - run: ls -l use-api/target/ + run: ls -l testphase/ # Start Spring Boot - name: Start Spring Boot From 7e6339fc90171a3c7328590eb5abdf88c4009bbd Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:36:13 +0100 Subject: [PATCH 025/148] Update maven.yml other name --- .github/workflows/maven.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a873e7ef9..ecae105bf 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -73,12 +73,12 @@ jobs: name: Constructed use-api #List target dir - - name: List target directory - run: ls -l testphase/ + - name: List directory + run: ls -R "Constructed use-api" # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar testphase/use-api-7.1.1.jar & + run: java -Dspring.profiles.active=test -jar "Constructed use-api/use-api-7.1.1.jar" & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From 154e149619ecffcbffd0f0d458c9f7b4b6ba8c63 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:39:18 +0100 Subject: [PATCH 026/148] Update maven.yml changed the artifact name --- .github/workflows/maven.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ecae105bf..0477fd81b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -41,7 +41,7 @@ jobs: run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase - uses: actions/upload-artifact@v4 with: - name: Constructed use-api + name: constructed_use-api path: testphase test: @@ -70,15 +70,15 @@ jobs: - name: Download Artifact use-api uses: actions/download-artifact@v4 with: - name: Constructed use-api + name: constructed_use-api #List target dir - name: List directory - run: ls -R "Constructed use-api" + run: ls -l constructed_use-api # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar "Constructed use-api/use-api-7.1.1.jar" & + run: java -Dspring.profiles.active=test -jar constructed_use-api/use-api-7.1.1.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From 341e796120e9af9e98a359b6712f042856d8ccc9 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:43:24 +0100 Subject: [PATCH 027/148] Update maven.yml where are my files --- .github/workflows/maven.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0477fd81b..c468719be 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -43,6 +43,9 @@ jobs: with: name: constructed_use-api path: testphase + + - name: List files + run: ls -R $GITHUB_WORKSPACE test: needs: build From 70c007ac16cfa8bed4c979750add50dd05910056 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:48:54 +0100 Subject: [PATCH 028/148] Update maven.yml access testphase folder --- .github/workflows/maven.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c468719be..9f8be1c94 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -44,8 +44,6 @@ jobs: name: constructed_use-api path: testphase - - name: List files - run: ls -R $GITHUB_WORKSPACE test: needs: build @@ -77,11 +75,11 @@ jobs: #List target dir - name: List directory - run: ls -l constructed_use-api + run: ls -l testphase # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar constructed_use-api/use-api-7.1.1.jar & + run: java -Dspring.profiles.active=test -jar testphase/use-api-7.1.1.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From 6e81c7597ee075256a675084c24f5ec067797f2e Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:52:04 +0100 Subject: [PATCH 029/148] listing directories removed the checkout for now aswell --- .github/workflows/maven.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9f8be1c94..28604cd99 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -57,8 +57,8 @@ jobs: steps: # Checkout repository - - name: Checkout code - uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact + #- name: Checkout code + # uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact # Set up JDK - name: Set up Java @@ -73,6 +73,10 @@ jobs: with: name: constructed_use-api + #List target dir + - name: List directory + run: ls -R + #List target dir - name: List directory run: ls -l testphase From 02dffd17d476fdc720a818f85ae50b69a77b45f8 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:55:04 +0100 Subject: [PATCH 030/148] checkout has to stay in for now --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 28604cd99..539f7a00f 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -57,8 +57,8 @@ jobs: steps: # Checkout repository - #- name: Checkout code - # uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact + - name: Checkout code + uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact # Set up JDK - name: Set up Java From 25c6e4d921c2a69cd2ea103fd8ca215a172c296d Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 09:59:12 +0100 Subject: [PATCH 031/148] there was no dir to begin with --- .github/workflows/maven.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 539f7a00f..fc8ed12fc 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -73,17 +73,11 @@ jobs: with: name: constructed_use-api - #List target dir - - name: List directory - run: ls -R - #List target dir - - name: List directory - run: ls -l testphase # Start Spring Boot - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar testphase/use-api-7.1.1.jar & + run: java -Dspring.profiles.active=test -jar use-api-7.1.1.jar & env: SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb From 8b1bf3212173cb50f202115b5b3b52e419b1e64a Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:08:56 +0100 Subject: [PATCH 032/148] removed the checkout again and also the maven --- .github/workflows/maven.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index fc8ed12fc..2afa66ea0 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -57,8 +57,8 @@ jobs: steps: # Checkout repository - - name: Checkout code - uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact + #- name: Checkout code + #uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact # Set up JDK - name: Set up Java @@ -66,7 +66,7 @@ jobs: with: java-version: '21' distribution: 'adopt' - cache: maven + #cache: maven - name: Download Artifact use-api uses: actions/download-artifact@v4 From a443548c59a5e0aef31401ff1edf713870872126 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 14 Feb 2025 09:22:56 +0100 Subject: [PATCH 033/148] removed graphql --- .../use/graphql/services/MClassGService.java | 36 ---------------- .../main/resources/graphql/schema.graphqls | 42 ------------------- 2 files changed, 78 deletions(-) delete mode 100644 use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java delete mode 100644 use-api/src/main/resources/graphql/schema.graphqls diff --git a/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java b/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java deleted file mode 100644 index 9c9bed7af..000000000 --- a/use-api/src/main/java/org/tzi/use/graphql/services/MClassGService.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.tzi.use.graphql.services; - -import org.springframework.graphql.data.method.annotation.Argument; -import org.springframework.graphql.data.method.annotation.MutationMapping; -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.stereotype.Controller; -import org.springframework.stereotype.Service; -import org.tzi.use.model.Attribute; -import org.tzi.use.model.UseClass; -import org.tzi.use.model.Operation; -import org.tzi.use.repository.ClassRepo; - -import java.util.List; - -@Controller -@Service -public class MClassGService { - private final ClassRepo classRepo; - - public MClassGService(ClassRepo repo) { - this.classRepo = repo; - } - - @QueryMapping - public Iterable classes() { - return classRepo.findAll(); - } - - @MutationMapping - public UseClass aUseClass(@Argument MClassInput mClassInput) { - UseClass tmpUseClass = new UseClass(mClassInput.name_mclass, mClassInput.attributes,mClassInput.operations); - return classRepo.save(tmpUseClass); - } - - private record MClassInput(String name_mclass, List attributes, List operations) {} -} diff --git a/use-api/src/main/resources/graphql/schema.graphqls b/use-api/src/main/resources/graphql/schema.graphqls deleted file mode 100644 index 35bfc3f81..000000000 --- a/use-api/src/main/resources/graphql/schema.graphqls +++ /dev/null @@ -1,42 +0,0 @@ -####Queries -type Query{ - classes: [Class] -} - - -type Class{ - name_mclass: String! - attributes: [Attribute] - operations: [Operation] -} - -type Attribute{ - name_attr: String! - type: String! -} - -type Operation{ - head: String! - body: String -} - -#### Mutations -type Mutation{ - aUseClass(mClassInput: ClassInput): Class -} - -input ClassInput{ - name_mclass: String! - attributes: [AttributeInput] - operations: [OperationInput] -} - -input AttributeInput{ - name_attr: String! - type: String! -} - -input OperationInput{ - head: String! - body: String -} \ No newline at end of file From aacce4f6dc0cb9f466fe95a02c56a22c4da3fd01 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 14 Feb 2025 09:23:10 +0100 Subject: [PATCH 034/148] added the checkout again --- .github/workflows/maven.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2afa66ea0..c098065fc 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -56,9 +56,9 @@ jobs: - 27017:27017 steps: - # Checkout repository - #- name: Checkout code - #uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact + #Checkout repository + - name: Checkout code + uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact # Set up JDK - name: Set up Java @@ -84,7 +84,7 @@ jobs: # Wait for Spring Boot to start - name: Wait for Spring Boot run: | - for i in {1..4}; do + for i in {1..5}; do curl --fail http://localhost:8080/actuator/health && break || sleep 10; done From f803b8e9e2d9633e2d2eb44a5d0a35480e730b00 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 27 May 2025 12:23:58 +0200 Subject: [PATCH 035/148] added funtionality --- .github/workflows/postmantestci.yml | 58 -------------- use-api/pom.xml | 5 ++ .../main/java/org/tzi/use/MClassFacade.java | 20 +++-- .../java/org/tzi/use/model/Invariant.java | 45 +++++++++++ .../org/tzi/use/model/PrePostCondition.java | 57 ++++++++++++++ .../main/java/org/tzi/use/model/UseClass.java | 72 +++++++++++++----- .../org/tzi/use/repository/AttributeRepo.java | 7 -- .../org/tzi/use/repository/OperationRepo.java | 8 -- use-api/target/classes/application.properties | 2 +- .../target/classes/graphql/schema.graphqls | 42 ---------- .../classes/org/tzi/use/MClassFacade.class | Bin 1900 -> 2756 bytes .../classes/org/tzi/use/OpenApiConfig.class | Bin 955 -> 955 bytes .../services/MClassGService$MClassInput.class | Bin 2411 -> 0 bytes .../use/graphql/services/MClassGService.class | Bin 1858 -> 0 bytes .../classes/org/tzi/use/model/Invariant.class | Bin 0 -> 1193 bytes .../org/tzi/use/model/PrePostCondition.class | Bin 0 -> 1505 bytes .../classes/org/tzi/use/model/UseClass.class | Bin 2382 -> 4048 bytes 17 files changed, 171 insertions(+), 145 deletions(-) delete mode 100644 .github/workflows/postmantestci.yml create mode 100644 use-api/src/main/java/org/tzi/use/model/Invariant.java create mode 100644 use-api/src/main/java/org/tzi/use/model/PrePostCondition.java delete mode 100644 use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java delete mode 100644 use-api/src/main/java/org/tzi/use/repository/OperationRepo.java delete mode 100644 use-api/target/classes/graphql/schema.graphqls delete mode 100644 use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class delete mode 100644 use-api/target/classes/org/tzi/use/graphql/services/MClassGService.class create mode 100644 use-api/target/classes/org/tzi/use/model/Invariant.class create mode 100644 use-api/target/classes/org/tzi/use/model/PrePostCondition.class diff --git a/.github/workflows/postmantestci.yml b/.github/workflows/postmantestci.yml deleted file mode 100644 index 71b3681f9..000000000 --- a/.github/workflows/postmantestci.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: CI with Postman Tests - -on: push - -jobs: - test: - runs-on: ubuntu-latest - - services: - mongo: - image: mongo:4.4 - ports: - - 27017:27017 - - steps: - # Checkout repository - - name: Checkout code - uses: actions/checkout@v3 - - # Set up JDK - - name: Set up Java - uses: actions/setup-java@v3 - with: - java-version: '21' - distribution: 'adopt' - cache: maven - - # Build the application - - name: Build with Maven - run: mvn --batch-mode --update-snapshots verify - - #List target dir - - name: List target directory - run: ls -l use-api/target/ - - # Start Spring Boot - - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar use-api/target/use-api-7.1.1.jar & - env: - SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb - - # Wait for Spring Boot to start - - name: Wait for Spring Boot - run: | - for i in {1..4}; do - curl --fail http://localhost:8080/actuator/health && break || sleep 10; - done - - # Run Postman Tests with Newman - - name: Run Postman tests - run: | - npm install -g newman - newman run use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json - - - # Cleanup - - name: Stop Spring Boot - run: pkill -f 'java -Dspring.profiles.active=test' diff --git a/use-api/pom.xml b/use-api/pom.xml index 97598e673..e8979dc9a 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -56,6 +56,11 @@ h2 runtime + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.5.0 + org.springframework.boot spring-boot-starter-test diff --git a/use-api/src/main/java/org/tzi/use/MClassFacade.java b/use-api/src/main/java/org/tzi/use/MClassFacade.java index 61c705236..7d0162495 100644 --- a/use-api/src/main/java/org/tzi/use/MClassFacade.java +++ b/use-api/src/main/java/org/tzi/use/MClassFacade.java @@ -2,9 +2,7 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; -import org.tzi.use.model.Attribute; -import org.tzi.use.model.Operation; -import org.tzi.use.model.UseClass; +import org.tzi.use.model.*; import org.tzi.use.uml.mm.MAttribute; import org.tzi.use.uml.mm.MClass; import org.tzi.use.uml.mm.MInvalidModelException; @@ -16,16 +14,22 @@ public static UseClass createMClass(UseClass aClass) throws UseApiException, MIn UseModelApi useModelApi = new UseModelApi(); MClass mClass; mClass = useModelApi.createClass(aClass.getName_mclass(), false); - //for each attr add for (Attribute attribute : aClass.getAttributes()) { - MAttribute tmp_mAttribute = useModelApi.createAttribute(mClass.name(), attribute.getName_attr(), attribute.getType()); + useModelApi.createAttribute(mClass.name(), attribute.getName_attr(), attribute.getType()); } - //for each operation add for (Operation operation : aClass.getOperations()) { - MOperation tmp_mOperation = useModelApi.createOperation(mClass.name(), operation.getHead(), new String[0][0], operation.getBody()); + useModelApi.createOperation(mClass.name(), operation.getHead(), new String[0][0], operation.getBody()); } - //TODO return the MClass for later to be saved inside the DB + + for(PrePostCondition prePostCondition : aClass.getPrePostConditions()) { + useModelApi.createPrePostCondition(mClass.name(), prePostCondition.getOperationName(), prePostCondition.getName(), prePostCondition.getCondition(), prePostCondition.isPre()); + } + + for (Invariant invariant: aClass.getInvariants()) { + useModelApi.createInvariant(mClass.name(), invariant.getInvName(), invariant.getInvBody(),invariant.isExistential()); + } + return aClass; } } diff --git a/use-api/src/main/java/org/tzi/use/model/Invariant.java b/use-api/src/main/java/org/tzi/use/model/Invariant.java new file mode 100644 index 000000000..2cdb722bf --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/model/Invariant.java @@ -0,0 +1,45 @@ +package org.tzi.use.model; + +import jakarta.persistence.Id; + +public class Invariant { + + @Id + private String invName; + private String invBody; + private boolean isExistential; + + public Invariant() { + + } + + public Invariant(String invName, String invBody, boolean isExistential) { + this.invName = invName; + this.invBody = invBody; + this.isExistential = isExistential; + } + + public String getInvName() { + return invName; + } + + public String getInvBody() { + return invBody; + } + + public boolean isExistential() { + return isExistential; + } + + public void setInvName(String invName) { + this.invName = invName; + } + + public void setInvBody(String invBody) { + this.invBody = invBody; + } + + public void setExistential(boolean existential) { + isExistential = existential; + } +} diff --git a/use-api/src/main/java/org/tzi/use/model/PrePostCondition.java b/use-api/src/main/java/org/tzi/use/model/PrePostCondition.java new file mode 100644 index 000000000..a771c748a --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/model/PrePostCondition.java @@ -0,0 +1,57 @@ +package org.tzi.use.model; + +import jakarta.persistence.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class PrePostCondition { + @Id + private String operationName; + private String name; + private String condition; + private boolean isPre; + + public PrePostCondition() { + } + + public PrePostCondition(String operationName, String name, String condition, boolean isPre) { + this.operationName = operationName; + this.name = name; + this.condition = condition; + this.isPre = isPre; + + + } + + public String getOperationName() { + return operationName; + } + + public void setOperationName(String operationName) { + this.operationName = operationName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + + public boolean isPre() { + return isPre; + } + + public void setPre(boolean pre) { + isPre = pre; + } +} diff --git a/use-api/src/main/java/org/tzi/use/model/UseClass.java b/use-api/src/main/java/org/tzi/use/model/UseClass.java index f43624150..af3059c8c 100644 --- a/use-api/src/main/java/org/tzi/use/model/UseClass.java +++ b/use-api/src/main/java/org/tzi/use/model/UseClass.java @@ -14,45 +14,75 @@ public class UseClass { private String name_mclass; // Unidirectional OneToMany relationship @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "mClass_id") // Foreign key column in the Employee table + @JoinColumn(name = "mClass_id") private List attributes = new ArrayList<>(); // Unidirectional OneToMany relationship @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "mClass_id") // Foreign key column in the Employee table + @JoinColumn(name = "mClass_id") private List operations = new ArrayList<>(); -// @OneToMany(mappedBy = "children", cascade = CascadeType.ALL, fetch = FetchType.LAZY) -// private List parents = new ArrayList<>(); - -// @OneToMany(mappedBy = "associations", cascade = CascadeType.ALL, fetch = FetchType.LAZY) -// private List associations = new ArrayList<>(); - + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "mClass_id") + private List prePostConditions = new ArrayList<>(); - // Getters and Setters + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "mClass_id") + private List invariants = new ArrayList<>(); public String getName_mclass() { return name_mclass; } - public void setName_mclass(String name_mclass) { - this.name_mclass = name_mclass; - } public List getAttributes() { return attributes; } -// -// public void setAttributes(List attributes) { -// this.attributes = attributes; -// } -// + public List getOperations() { return operations; } -// -// public void setOperations(List operations) { -// this.operations = operations; -// } + + public List getPrePostConditions() { + return prePostConditions; + } + + public List getInvariants() { + return invariants; + } + + public void addAttribute(Attribute attribute) { + attributes.add(attribute); + } + + public void removeAttribute(Attribute attribute) { + attributes.remove(attribute); + } + + public void addOperation(Operation operation) { + operations.add(operation); + } + + public void removeOperation(Operation operation) { + operations.remove(operation); + } + + public void addPrePostCondition(PrePostCondition condition) { + prePostConditions.add(condition); + } + + public void removePrePostCondition(PrePostCondition condition) { + prePostConditions.remove(condition); + } + + public void addInvariant(Invariant invariant) { + invariants.add(invariant); + } + + public void removeInvariant(Invariant invariant) { + invariants.remove(invariant); + } + + //Constructors public UseClass(String name_mclass, List attributes, List operations) { diff --git a/use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java b/use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java deleted file mode 100644 index 237e34ae4..000000000 --- a/use-api/src/main/java/org/tzi/use/repository/AttributeRepo.java +++ /dev/null @@ -1,7 +0,0 @@ -//package org.tzi.use.repository; -// -//import org.springframework.data.jpa.repository.JpaRepository; -//import org.tzi.use.model.Attribute; -//@Deprecated -//public interface AttributeRepo extends JpaRepository { -//} diff --git a/use-api/src/main/java/org/tzi/use/repository/OperationRepo.java b/use-api/src/main/java/org/tzi/use/repository/OperationRepo.java deleted file mode 100644 index ae27148ff..000000000 --- a/use-api/src/main/java/org/tzi/use/repository/OperationRepo.java +++ /dev/null @@ -1,8 +0,0 @@ -//package org.tzi.use.repository; -// -//import org.springframework.data.jpa.repository.JpaRepository; -//import org.tzi.use.model.Operation; -// -//@Deprecated -//public interface OperationRepo extends JpaRepository { -//} diff --git a/use-api/target/classes/application.properties b/use-api/target/classes/application.properties index dd694a400..943c06f5f 100644 --- a/use-api/target/classes/application.properties +++ b/use-api/target/classes/application.properties @@ -4,7 +4,7 @@ spring.graphql.graphiql.enabled=true spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.main.allow-bean-definition-overriding=true -server.port=8080 +server.port=8090 # /api-docs endpoint custom path springdoc.api-docs.path=/docs diff --git a/use-api/target/classes/graphql/schema.graphqls b/use-api/target/classes/graphql/schema.graphqls deleted file mode 100644 index 35bfc3f81..000000000 --- a/use-api/target/classes/graphql/schema.graphqls +++ /dev/null @@ -1,42 +0,0 @@ -####Queries -type Query{ - classes: [Class] -} - - -type Class{ - name_mclass: String! - attributes: [Attribute] - operations: [Operation] -} - -type Attribute{ - name_attr: String! - type: String! -} - -type Operation{ - head: String! - body: String -} - -#### Mutations -type Mutation{ - aUseClass(mClassInput: ClassInput): Class -} - -input ClassInput{ - name_mclass: String! - attributes: [AttributeInput] - operations: [OperationInput] -} - -input AttributeInput{ - name_attr: String! - type: String! -} - -input OperationInput{ - head: String! - body: String -} \ No newline at end of file diff --git a/use-api/target/classes/org/tzi/use/MClassFacade.class b/use-api/target/classes/org/tzi/use/MClassFacade.class index 8d183f1872b81f0850a9a77d50f966b4593f4012..f25b458e8e4abe56b506ae8640eac6ef651cc46a 100644 GIT binary patch delta 1053 zcmZuvOH30{6g`iAri`zE6{uJ~QL8a6rggzWNlg5Zpz^6-{D3;pv5wMC=?n;{)c^kj znT;+?3>&u+lPWHZCb%(ifr)WR!rH{OhJg3cw6Vp-oOj>7=iK|woALXb5sir8fqx6N7epN zF;PZ4A{+-%&QL*(I+JQj5gj^|xGIW=IgW^;M8#b0SUX3TNODT%XA1TSj+5BP;Lr@3 zBtt?sM-NUjRQIJ+#Z-&uGYo98#%z9T+~yJA#GE%>%xM;G&vGcjt(!*fOAIL~O-Yz! zvyZ{I(q^6^qZca2IdNJ!E6uv-#d!|xpY(1$IwIH?n>hM~2e)Rl3~Pp|CQMD~7hVz^ zI+6_KSugn^3_W=h6LYohe4$xF>dj}{8rD~lEc!zX{CEAr@ z7$ek##B7#$4qBPD*Xd`QEzQ~B?RvHJBap%NX{=@F*gB1RhUaLsUOG3WsWwZs{e`tK zk^BrF(Z0hTY@9}bp~jv;r+`BOjtV%Q!70*zCHB(Ij!kkfvy!)Yqt&U0f2B8@NeBUHDC{Z_}-M@C$cvmu~YOjijQgZ;lJWr_QKu)gE5XyhoOJ^8 delta 351 zcmXAjOD{uF6otRj-rIBU4UM!)U8NJRTpEp-)QE}1tLm-PoA?J3BNB<2pAmn+R1HuA zBO@at|G>;I5GlJ?PO|piXRW=~eocMFy|?=F3oyY^)q9FYH8c0Iq%x=a#@bb6O;smN z;KbFwDLAFdG!YRasIZ9%&dM|_RY|pjM^rVW=L8!xG*c98`WG-yNhX&C7R5xCl^+_x zmHBjfRKM}uY^obp`;E<5lN}d#x zv@=Bq$M{^($t7Lk8KV-Gr;R0+v4qXA!m4x<&l>Ae9nLAUA?GGIVUvoSxh4NTR-KGS d4`>E8*>8q^aKmPVZ4tyoxWk?-9>^5o@DD)uG!y^; diff --git a/use-api/target/classes/org/tzi/use/OpenApiConfig.class b/use-api/target/classes/org/tzi/use/OpenApiConfig.class index b08c0e1784d02e562e1d4d5c67021edb7f289416..88c2463d309b3be2f286196f0340fd5ea91d8e65 100644 GIT binary patch delta 13 UcmdnZzMFjmA2XxnWPau~039*|(EtDd delta 13 UcmdnZzMFjmA2XxHWPau~039s@&;S4c diff --git a/use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class b/use-api/target/classes/org/tzi/use/graphql/services/MClassGService$MClassInput.class deleted file mode 100644 index 9541a7ea99c0899d130de247dc8fe4f9e110265e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2411 zcmbtVUvtw&5dU4AL{6d*+X*Sq5(orpD}WkW2vjCCghC8X=rl|o+J}zp+}HwHXQWf6 z?Pux(%rw)PJoE$bp&0fgIhGO^41JJvySKmnzpJxPnH%CkHCw@y<@FqGh*&iP;Dx zC)q+Q8%oDD>rNme$&!xQNK$mUZ%apbL5Tu9tz#ZvFyy6()iP|A>!0bgRXORUGICbO zIebY*+IG<15PO`V`ag`+l+N=y7I1-*&tHYMOHprszQ&Z-&l)dyQ(Bc@7$$a{mS@Y* zCwI+bDXnHw)S-}EbG=srYt0%C@vK*h2yv^N@*}D7F|*cjy0XhK8fSE-?s$AV>@>Ll z+-|t!bg3?yw!3Tlj-nIhsBAlwt-F~3KA|xwwE3*wKe|2Lg)J`IV(%y0r`DC+Cp*E% zgZfx5kHtJlJe^3DlDYDLPK@TW#&A0AQmWoeWXCMIB4$rpf1(&xPA~^KmhFk*FzH}u zvUf!2H~Aw+RdhDHFm9-wKx4Jd1Gy;zso@U8@+S;0jZbfh6&?s714$byE@F^Jm0>Zp zgslFKvHDA7hC!oenx5j!IMyfe02>+}>i7|l7%ueJmLGc3>2Nd7Yhs1QtkE;f@Frav z$J-Y#xfu&?+TNbagQdC4lr$8KS1#f@pHIB z?{UI|Fjwhq#PawWWugcf*;V&*k!9u0Tx2tc3Z3U8|J2=La+<{@(reJ&bdJEFD-ZyQ z%gZPd=o*<+4zAEwDc6icQj6Dg968~W9*ZPC73m*yeE|Fn@YhiA1>8vBRWham${Wjv z`0Bs#aftb&l;mMjVU*ufM{$@D4U8FoL;Fw^V~H9@X;~rTDhX-u^f2IyQJgo)=IlTv z#o?8FOWpEar0y1ON8eT4rSB5eFz&c)zh%4ady-V$_XBCk!@@nR;XWP{w?wh!v5HNq LRt-mL9utW_|9Ne3kt2QbBOx=xK(jWf@An!Z2BHbjvu1vV)3?DqM!8NDVywoAlB|cmu`btzUgF5o%lZ zMB;T;eV!zbHZq%`+%xtw5l0NQcHULdULtj*c0B82FwH6s;jn`vE{GUjmH!Iv&hV4mT29y#V}=d+ux zhjB`RRYM+#p96bY$|TFfO1hzy36DApIKxoknl?96EfP|HG-rccaPgHzMzK&_ z%P34Ln87(yvGWYK>K_Lfr5UvwU8C(q7hj{!P)hi=V7Qnk%8K6{ikRz%Cc}mL_}VqP z#JfuRG8}HpP&`h9O`)FiO`mqA+fk4EU9P0Dhnpq6B}szI1@1ArQ!*vfI#hY9w$X5I zxAHdWbxoR45JHwWUv5Vc&Tp@}R&(cuKKy+myiL@1lkz(??++e2ze!G!uAVqgt^BPr1>Ws$3|>z0Zl& zQiC)Qp{7DqHlkGZ#F{kiI#ZluSIk_Y(f7#^31uQ8y%P&>H43$gd|xOc%!)bM9Xa%H zND{RASR}e5%=bd=?5>BQP_|&EyQ{fLLu26}O>cm{C^L>}HA(9OXwZ9+tTj3{=at2` zV2ewC!uf-&2`th35MhB?lyD4Y%3LCAE<@uou8>83@Q9Vs-&I^Ayy3iQZNvEn&O3a; z@H_2hoKtiL%v&zwXBaZB>lSl^ya9u{MZXN+;P#NUPg$FMYJX$qr=>SIM$bul&b~#h zV h_vt->?<~X+x5)mUo>hBFQw0xbRU!NwiT)7t9{~Gk`~(01 diff --git a/use-api/target/classes/org/tzi/use/model/Invariant.class b/use-api/target/classes/org/tzi/use/model/Invariant.class new file mode 100644 index 0000000000000000000000000000000000000000..8c6b2c68eaa88580c568475a52a1ff3a04bf3d8e GIT binary patch literal 1193 zcmaJ<(QXn!6g>kJ3I$3j#a6^tt9GG{``}|ulWH_+LTX|S4}Du;f>W1Wv%3)Wn|#nj zV&a1z;71wH>~5fituJ%uPVPDP+;iv8-(SB0oWdv|g>(*?B36(Us9aeS%d{&w?lTTq_u>#1H59&iOIevLFwt{4I}W?9B9#+2Sy z7`Y?HRlf7z@T@a?#wZw9+CL$_hh=wo>MsVuGALs^yoE*B!ChvWpb-<;tjzGOrU}}I zQ{>u5Q@ilQK1TJHp4@WQvE-H!WQ&sp${K0R`@%8Fw}r zBk4bo`^KUav~)cgcuSIfKM`D71UC}FRqQ5ou6$kSyqgH#T29rU8L)fTt~NXJ?3gO*OSnR FgMZd$xoH3Z literal 0 HcmV?d00001 diff --git a/use-api/target/classes/org/tzi/use/model/PrePostCondition.class b/use-api/target/classes/org/tzi/use/model/PrePostCondition.class new file mode 100644 index 0000000000000000000000000000000000000000..d688848478b20b77cd0818e78468f3b37d7f2223 GIT binary patch literal 1505 zcma)5+iuf95S>k&gan7Cmy|Z;)(bRAFGea76-AY*A|#}$ttiSv-yCNN+a}(~c0l5Z z58?qNA|xL806q$F#x_lwx`LOT-SO->XXlK6{r>Tji1ui+Kq*S+$S^5GSwW>U`@L;- zY`1M4HP56I2+BTJt_pSqrK`0@o^DV+M+K8^k|}6Odu=QDsI0y(t*&m#j&R1V_gq&8A)zm54s7SP7uXh5_{tBY>qzTWYX?mGP%LQT zK)Ld;-)&0ojg9N9P&;;~VS9?tancChDd4Rf{QJ$oepbEu%Kyon)*5i3ErX-WO`ECK zu3kr_f2FdVz|5dIfJO%7a4FiE$c;E<;={-hhNHPzB*RV{)lgiz$89g1=)UL3mx}vU z9yfiH9Tv15_R8SK+M#?llU5zRl*_$z6IzBTELFM zQABs>E+PZm!^!}kK$JnOFhG56K)L$*fQt2v0hQ`yV?fhG)Cy>cCV@Idd71|P4AwGm z=0cVy5mL+o%=lTn3C0!7kO7HKKI zyo+k4$cE1t%I4pnK#~CsBg{rs7c#T4OhLNP^ROWc8n zi9$-_Le>(6JW3W)8W&yD7%XB3J`tGm z{4FE=*)iIIZ8W{Q-7xM3cBNqjfk45vn)cIXEgp@VFRWLV(XiYtV?Fd8cdIPHJ}qJ= zh6IMJkT0w4(5C0E*tQ)y4a0PTFtRKbF&tTXE!($3$8!S-Fj~Ye`FgD7+jqPmtaxtS zQM2Pk?2eoq_m$;4mKz2I?7?InpB3>r_6m$dv{Wd8oK>$2?3vxhceVP$u7%~f2h#V8 zBKAqgPkg)Sy|RZejRSccEMf+SNWGh7>_x*%j_ZVrM4p}7%;Si_?rzK_-?v`N9EWfi z2L$%6wcXHZ+M7<`R2%k^>w00FtiY@(ydQmv`;+ItH0oAp8J4m$mg{AKo$Jn) zYlUs!7BEt3UW#DeU$v!<`sGD>AE3ue%O@_S4oJ>+YqqiK+8f?&%Y99Ye9a1KR-NcG zTH8uIz45wb(>k|gngYX~-+FGjYf?6=kz+v#frDE2o1WuVyhgj}(tA+W5mRbLb@kNY z>hzP+YNt%1lot9B;ZCZ8BFBD0Eq975@)+5&!!%!ZPFcZW`YfPvMebGrfMu?J?62EU&$|J%ka=$CdSdj59%i11uo2*3Ds|5CI z)(RJNs8<3qp3)^Fo|-R5@w`qc>*IB;RXp{I&4%&P;t3qrrI|L1qt`keRp5vw z+Yg)sCgY^jGjZ-p{fykzd>q~B>@9unU2B!QdL?jvdlyemom3+zr^iz9$@h04yI8Ud zgWiC>_EIXI&Rne?3slls)kXdA=v75l)+|#OQzE{1yd}cO_e1Mm+ppQz9odJ5JB{VE zJg>M>BUtVE)AZaeuU<83p3e^ftJUHWWnA-W?WXO9Wz6uPo@T?}!8<=3AaIN$c|Xqk zfcymDbvAmQi{_>|F7bEbA%u;SIEB*>VBid0<^!DN3_k{x&$&K*_@$tHzU? zd|y6eB)NdEc)h@k4BiFrJ4$aLevMN6npc@TD9lA(i?IR9xWtjbH&|rIv~xb~d`#mU zYj~L;SF|97G)O5EWQibGwICyDkkgqU6@pyTf{dj>&SrvqOOWfh!K>8d8nqdas!`DV ziQh3XfP24jJOHVyTr5!j0vAAPI~m(1+Dfgz!!nTsZe}7*X%H_GvD^dk7EBGtLI%f0 zB3{lwyp5HJ<7y_Nj^kA#R(c@b!S@=DBN-g86Y)j{;u_W?jvJYXI*vDqc&i8EU2JMN zj%9FMA>wKV;ywHjalD_2sN=Xs#PuGCGkCztlJ)pEav0?OO6eW;m;S`z`|oh{E%M#R zLicf``#4rQ@fMo|k^IM28j@sO4C zC}LQOW2^eUk~CQIN!qG>lFc$lug-pub93Y$&z<93+&CUltrndJ%@%M6|*8T`Vr%yQwQ zGU#@dY2=Ag)o`tmYkga-EGUi(2}jB2P{PNH_yP0(mrs|<6ps$T)=;q{8u4K=pU@bf Pkg_#Ci%u?i=vcsiU65ma literal 2382 zcma)8?Q+{h6g_JvaT7ZqxM`qCN!{|5s7XZ&H3g?`-IR7V=t~+Tk=S9 zneZSy0>5FVnGP_+1MpA`XIHZ1xauT-w7c4S&pr3tt2_GlzrX$g(7@ek_MRHp4V1g`@2AGcV!R=6kXXua2|{C8Dq+@GdVS@~(DB@02J=`b;H?tMI7_!Q!p^}n z)d~fswj9?9>jL?;_5A|Q37j=X2D;(<@=)W?U=a&Nyo2)vESIo?3j%Ygoi-tYY_|o@ zt&QXnMX9Yn7C8TC;D%05?K^>U&{YlB^}>jxz*beRd&3(P95Gfw^ET_Oar}O}xHOg-9}~1aZqlj%f!ATzl>1$pzKG zi5>(#9Y*3|6udFou`%gL!Ia(jStqr0TsU?_EM9Oj;7OT{#mh1uO+wSz$%^{=_({r8 z%cyONsS)4Jut?pr?^6VhtX*&5x72+{x7qBlZ?5XOA#l@xXMXcN&+T~a1H0w<9GbG< z=UA}sd96WDxnT{LI2Gslk>$B^$bv+8((5YMoF12aUNrlPxm)E~dtLq!Lg78Uj}IQ> zLwrP+wE*k9;owYstW)`%q4O1N@VUuIHdn!Q(s~K;y9s@jPfZHA%xj<&8Q^1F<4NE; zKH*b4*BLs;b;`PO1n~!VIcRT93FJ9RrW#=>vWgKjdX&Dvr?|npaUz9rB31^GNT({P ze3l7P90$4nMv$8XDdY2)$!{#s1X)|wE6iDcWATSqSUN%>-4;#0)`ot$d4!_QJZ~~z zMS=S-=)b^HFJc)r7Ice+yTx+V4FfAePt>qtH5f5&0lm|O%@b*;p1!LX9rc~XyGVeV z;l34D0@*E%_AeTQAs=2`bgS9M35!b7Tl{l~Rr%I109M`{ eF%4EW<#{j??7>Lmti*wGxJ^nq+)2LS2Jk=GgbykJ From 4d2dfac2edce23488ae370540d7601f506ef8874 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Tue, 27 May 2025 14:37:29 +0200 Subject: [PATCH 036/148] Update application.properties pipeline took it as 90 for some reason, will do another commit to change to 80 again --- use-api/src/main/resources/application.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index dd694a400..520d9b7fe 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.graphql.graphiql.enabled=true spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.main.allow-bean-definition-overriding=true -server.port=8080 +server.port=8081 # /api-docs endpoint custom path springdoc.api-docs.path=/docs @@ -17,4 +17,4 @@ spring.data.mongodb.username=rootuser spring.data.mongodb.password=rootpass spring.data.mongodb.database=use-database spring.data.mongodb.port=27017 -spring.data.mongodb.host=localhost \ No newline at end of file +spring.data.mongodb.host=localhost From d23e0d33b4ffaf5abcf6a4ab07ed1c64115836ca Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Tue, 27 May 2025 14:37:42 +0200 Subject: [PATCH 037/148] Update application.properties 80 again --- use-api/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index 520d9b7fe..4a37a9cfe 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.graphql.graphiql.enabled=true spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.main.allow-bean-definition-overriding=true -server.port=8081 +server.port=8080 # /api-docs endpoint custom path springdoc.api-docs.path=/docs From deee6ae21166a51f59ab1a687e9b7d154e3eda4f Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 27 May 2025 14:46:59 +0200 Subject: [PATCH 038/148] localhost 8080 no use anymore --- .../java/org/tzi/use/UseAPIApplication.java | 2 +- use-api/target/classes/application.properties | 4 ++-- .../classes/org/tzi/use/OpenApiConfig.class | Bin 955 -> 955 bytes 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java index 9d2cb6670..f87877fcc 100644 --- a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java +++ b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java @@ -8,7 +8,7 @@ import org.tzi.use.model.UseClass; import org.tzi.use.model.Operation; import org.tzi.use.repository.ClassRepo; - +//localhost 8080 not in use anymore @SpringBootApplication public class UseAPIApplication { public static void main(String[] args) { diff --git a/use-api/target/classes/application.properties b/use-api/target/classes/application.properties index 943c06f5f..4a37a9cfe 100644 --- a/use-api/target/classes/application.properties +++ b/use-api/target/classes/application.properties @@ -4,7 +4,7 @@ spring.graphql.graphiql.enabled=true spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.main.allow-bean-definition-overriding=true -server.port=8090 +server.port=8080 # /api-docs endpoint custom path springdoc.api-docs.path=/docs @@ -17,4 +17,4 @@ spring.data.mongodb.username=rootuser spring.data.mongodb.password=rootpass spring.data.mongodb.database=use-database spring.data.mongodb.port=27017 -spring.data.mongodb.host=localhost \ No newline at end of file +spring.data.mongodb.host=localhost diff --git a/use-api/target/classes/org/tzi/use/OpenApiConfig.class b/use-api/target/classes/org/tzi/use/OpenApiConfig.class index 88c2463d309b3be2f286196f0340fd5ea91d8e65..b08c0e1784d02e562e1d4d5c67021edb7f289416 100644 GIT binary patch delta 13 UcmdnZzMFjmA2XxHWPau~039s@&;S4c delta 13 UcmdnZzMFjmA2XxnWPau~039*|(EtDd From eb20fcb987ac4d3f09374a79a85df301d692761b Mon Sep 17 00:00:00 2001 From: husakki Date: Wed, 18 Jun 2025 08:50:32 +0200 Subject: [PATCH 039/148] Update use-webapi.postman_collection.json maven testintegration --- .../postman_collection/use-webapi.postman_collection.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename use-api/src/{main/resources => it/java/org.tzi.use}/postman_collection/use-webapi.postman_collection.json (100%) diff --git a/use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json similarity index 100% rename from use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json rename to use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json From 3be71e6ec5fb898ca9471f11b4ce2f5d0cbc4692 Mon Sep 17 00:00:00 2001 From: husakki Date: Wed, 18 Jun 2025 08:50:49 +0200 Subject: [PATCH 040/148] operation renaming --- .github/workflows/maven.yml | 2 +- .../main/java/org/tzi/use/MClassFacade.java | 5 ++-- .../java/org/tzi/use/model/Operation.java | 23 +++++++++---------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c098065fc..ec87b62f1 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -92,7 +92,7 @@ jobs: - name: Run Postman tests run: | npm install -g newman - newman run use-api/src/main/resources/postman_collection/use-webapi.postman_collection.json + newman run use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json # Cleanup diff --git a/use-api/src/main/java/org/tzi/use/MClassFacade.java b/use-api/src/main/java/org/tzi/use/MClassFacade.java index 7d0162495..cac763d90 100644 --- a/use-api/src/main/java/org/tzi/use/MClassFacade.java +++ b/use-api/src/main/java/org/tzi/use/MClassFacade.java @@ -3,10 +3,8 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.model.*; -import org.tzi.use.uml.mm.MAttribute; import org.tzi.use.uml.mm.MClass; import org.tzi.use.uml.mm.MInvalidModelException; -import org.tzi.use.uml.mm.MOperation; public class MClassFacade { @@ -18,8 +16,9 @@ public static UseClass createMClass(UseClass aClass) throws UseApiException, MIn useModelApi.createAttribute(mClass.name(), attribute.getName_attr(), attribute.getType()); } + //parameter liste wird noch nicht unterstützt. -> daher new String [][] for (Operation operation : aClass.getOperations()) { - useModelApi.createOperation(mClass.name(), operation.getHead(), new String[0][0], operation.getBody()); + useModelApi.createOperation(mClass.name(), operation.getName(), new String[0][0], operation.getBody()); } for(PrePostCondition prePostCondition : aClass.getPrePostConditions()) { diff --git a/use-api/src/main/java/org/tzi/use/model/Operation.java b/use-api/src/main/java/org/tzi/use/model/Operation.java index 59c452701..de9da7b68 100644 --- a/use-api/src/main/java/org/tzi/use/model/Operation.java +++ b/use-api/src/main/java/org/tzi/use/model/Operation.java @@ -1,13 +1,12 @@ package org.tzi.use.model; -import jakarta.persistence.Entity; import jakarta.persistence.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document public class Operation { @Id - private String head; + private String name; private String body; @@ -26,12 +25,12 @@ public void setBody(String body) { this.body = body; } - public String getHead() { - return head; + public String getName() { + return name; } - public void setHead(String head) { - this.head = head; + public void setName(String name) { + this.name = name; } // public UseClass getMclass() { @@ -43,16 +42,16 @@ public void setHead(String head) { // } //Constructors - public Operation(String head, String body) { - this.head = head; + public Operation(String name, String body) { + this.name = name; this.body = body; } - public Operation(String head, UseClass mclass) { - this.head = head; + public Operation(String name, UseClass mclass) { + this.name = name; // this.mclass = mclass; } - public Operation(String head) { - this.head = head; + public Operation(String name) { + this.name = name; } public Operation() {} From 4f14f28e68fcda830fb4c4aace4b789660b81f4f Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 25 Sep 2025 15:25:10 +0200 Subject: [PATCH 041/148] Add Dockerfile and clean build artifacts Added a Dockerfile for containerizing the use-api service. Removed all build output, configuration, and test artifacts from the target directory to clean up the repository. --- use-api/Dockerfile | 20 + use-api/target/classes/application.properties | 20 - use-api/target/classes/docker-compose.yml | 28 - .../classes/org/tzi/use/MClassFacade.class | Bin 2756 -> 0 bytes .../classes/org/tzi/use/OpenApiConfig.class | Bin 955 -> 0 bytes .../org/tzi/use/UseAPIApplication.class | Bin 2380 -> 0 bytes .../classes/org/tzi/use/model/Attribute.class | Bin 1257 -> 0 bytes .../classes/org/tzi/use/model/Invariant.class | Bin 1193 -> 0 bytes .../classes/org/tzi/use/model/Operation.class | Bin 1273 -> 0 bytes .../org/tzi/use/model/PrePostCondition.class | Bin 1505 -> 0 bytes .../classes/org/tzi/use/model/UseClass.class | Bin 4048 -> 0 bytes .../org/tzi/use/repository/ClassRepo.class | Bin 339 -> 0 bytes .../rest/controller/RestApiController.class | Bin 2395 -> 0 bytes .../use/rest/services/MClassRService.class | Bin 1530 -> 0 bytes .../use-webapi.postman_collection.json | 484 ------------------ use-api/target/maven-archiver/pom.properties | 3 - .../compile/default-compile/createdFiles.lst | 11 - .../compile/default-compile/inputFiles.lst | 12 - .../default-testCompile/createdFiles.lst | 1 - .../default-testCompile/inputFiles.lst | 1 - .../2025-01-20T09-17-37_242.dumpstream | 5 - .../org/tzi/use/RestApiControllerTest.class | Bin 312 -> 0 bytes use-api/target/use-api-7.1.1.jar | Bin 16808 -> 0 bytes 23 files changed, 20 insertions(+), 565 deletions(-) create mode 100644 use-api/Dockerfile delete mode 100644 use-api/target/classes/application.properties delete mode 100644 use-api/target/classes/docker-compose.yml delete mode 100644 use-api/target/classes/org/tzi/use/MClassFacade.class delete mode 100644 use-api/target/classes/org/tzi/use/OpenApiConfig.class delete mode 100644 use-api/target/classes/org/tzi/use/UseAPIApplication.class delete mode 100644 use-api/target/classes/org/tzi/use/model/Attribute.class delete mode 100644 use-api/target/classes/org/tzi/use/model/Invariant.class delete mode 100644 use-api/target/classes/org/tzi/use/model/Operation.class delete mode 100644 use-api/target/classes/org/tzi/use/model/PrePostCondition.class delete mode 100644 use-api/target/classes/org/tzi/use/model/UseClass.class delete mode 100644 use-api/target/classes/org/tzi/use/repository/ClassRepo.class delete mode 100644 use-api/target/classes/org/tzi/use/rest/controller/RestApiController.class delete mode 100644 use-api/target/classes/org/tzi/use/rest/services/MClassRService.class delete mode 100644 use-api/target/classes/postman_collection/use-webapi.postman_collection.json delete mode 100644 use-api/target/maven-archiver/pom.properties delete mode 100644 use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst delete mode 100644 use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst delete mode 100644 use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst delete mode 100644 use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst delete mode 100644 use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream delete mode 100644 use-api/target/test-classes/org/tzi/use/RestApiControllerTest.class delete mode 100644 use-api/target/use-api-7.1.1.jar diff --git a/use-api/Dockerfile b/use-api/Dockerfile new file mode 100644 index 000000000..e98fbf05f --- /dev/null +++ b/use-api/Dockerfile @@ -0,0 +1,20 @@ +FROM maven:3.8-eclipse-temurin-17 AS builder + +WORKDIR /app + +COPY pom.xml . + +COPY src ./src + +RUN mvn package -DskipTests + + +FROM eclipse-temurin:17-jre-alpine + +WORKDIR /app + +COPY --from=builder /app/target/*.jar app.jar + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/use-api/target/classes/application.properties b/use-api/target/classes/application.properties deleted file mode 100644 index 4a37a9cfe..000000000 --- a/use-api/target/classes/application.properties +++ /dev/null @@ -1,20 +0,0 @@ -spring.application.name=usewebapi -spring.jpa.hibernate.ddl-auto=create-drop -spring.graphql.graphiql.enabled=true -spring.h2.console.enabled=true -spring.h2.console.path=/h2-console -spring.main.allow-bean-definition-overriding=true -server.port=8080 - -# /api-docs endpoint custom path -springdoc.api-docs.path=/docs -springdoc.swagger-ui.operationsSorter=method -springdoc.swagger-ui.filter=true - -# mongoDB connection -spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=rootuser -spring.data.mongodb.password=rootpass -spring.data.mongodb.database=use-database -spring.data.mongodb.port=27017 -spring.data.mongodb.host=localhost diff --git a/use-api/target/classes/docker-compose.yml b/use-api/target/classes/docker-compose.yml deleted file mode 100644 index 9222b6e7c..000000000 --- a/use-api/target/classes/docker-compose.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: "3.8" -services: - mongodb: - image: mongo - container_name: mongodb - ports: - - 27017:27017 - volumes: - - data:/data - environment: - - MONGO_INITDB_ROOT_USERNAME=rootuser - - MONGO_INITDB_ROOT_PASSWORD=rootpass - mongo-express: - image: mongo-express - container_name: mongo-express - restart: always - ports: - - 8081:8081 - environment: - - ME_CONFIG_MONGODB_ADMINUSERNAME=rootuser - - ME_CONFIG_MONGODB_ADMINPASSWORD=rootpass - - ME_CONFIG_MONGODB_SERVER=mongodb -volumes: - data: {} - -networks: - default: - name: mongodb_network \ No newline at end of file diff --git a/use-api/target/classes/org/tzi/use/MClassFacade.class b/use-api/target/classes/org/tzi/use/MClassFacade.class deleted file mode 100644 index f25b458e8e4abe56b506ae8640eac6ef651cc46a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2756 zcmbVONpl-T6#m+hJ+{nOD?U z$xvc)L5-a^l$4%Ta^nRx1POrk>%Bp2zDsnB7%9N#5V&Bc8@c=_mvzEQ8*s)1S7_5ngt*(2e zFrpZiaEjx!2*iI35-o5^XH*6bLNg5spXk7(=@q z6W1}rvQJ#T3N#1o~-?Ne6vS&+dpTKf^JN8TZPrb%xEmy0V|Idhh-+xXvsYp5sUg8M-MT^F?J| zH_QoL%c>PMW*LrG2i(q$T3`q%%yT?1uGv9`To>Y{6q^eii;f1)+7idISQ9zox)k6G z94jKp8&!iG3AtY4xQLhO<*+lP);+`JyHc%Qq5745Ui(^?mUgdj$W98)Xj^hol{J%6 zDC3(#E+T|96pmNLcJ$~Yxwnc^w9#6%sHkhC^v14zqGK@q#U~flAcr(9dlc7bFBdcCB^!wP^ zs}zLQo#Nn+b#tB0*ioo?gBVWun6FDF@}fHVGMPU8bCDzO*9(x6r+De|BXY} z!M?Y)O&Y~EsC$=aaEE6X* zhS^iQILh!1PSWHA!_SC}1f#>d7@{T_EF&g{2g^9S{Oz5;i1oOaHSDlPJ*=@n;5Upn z2<}7~Q^dVN+-JSqxWi3(xO0N_f*8(=;l(mmiT?-jFM0V0_+X>3C?I_MLs6LA_R(M^5q0F|F#+ xh=TMntq-I5Hu@w;5~30Y{zdc_TCB+#XL8n=#PJC+nuz%+J||0G(o+Mz`VaiL`o;hN diff --git a/use-api/target/classes/org/tzi/use/OpenApiConfig.class b/use-api/target/classes/org/tzi/use/OpenApiConfig.class deleted file mode 100644 index b08c0e1784d02e562e1d4d5c67021edb7f289416..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 955 zcma)*&2Q5%6u_U?c7<-xG8iy6Soj(%VsQ(XX&}_9gRN4uRx4COoSe)}y(V@QJDuRa z;)H}IF1ztZA)eD}hy&UZ={fKF7yJ3w?;k$_pb6Cy%t5XQ`9&zeJb}tFn=l$N8Pbk_ z%mYJU{*92ryd{v^toDm=g}{nRLTbJWnrcovV=kLx(Nc0CLIU}gI^qP%o{;a#>xeP+y?q0j_Yz5iBxO`z0MX%g`FA}jMxKiA?S&|xZ#hH5u@^{<2d|-bQbFgDx$blkIy&%;_(KZT9DHvfa zU-4t_ozv{L2`n6O9VB9GYZBPVxVvp|Nk76A^*+{gh`ecjjsg*~!+B#eSNEu06KmgeN-V z&DGr+>X8Vz)abbsj5m!&nDSoN+j{BNobv*?G(m*=(3r8_p)?d`nEGy@Vmn1Dh_Yew zBjwYWX@h6g>U2M~5B3m3^Tcuya4*=ASs?9Y2^PasBNpNA#v%7piSxN^0kD5$r*WvX z+1ajb*We)(@gmrV;EPuQB z9-{9C<}5YfCRV+rVHs{~xC3_^u!8n`8dhOV!+m(5VI7os_BbO30BmZoAfp;O?ET8n+pB~ z|BQaB(iz6jj=#zAxtlcEwo3;mlg*xU&)a>@bI;A+|Gs_$AdjC+^r7FtKoWx(5=gy} zyV9ylr)I5IUZ`pyF!aE7>|jBlKRaDEkPx`!dNnKf#kN|$vYz-VzqXWbHtTj(2Da;% zFfn2vnZzl)CorRp{ibI-wQWx})X%QBV^v%?uu7pa;>i?V%Mqw#i@h=mb?N)LXAw;) z(7|%k#kj~-*9p|iz$&=Twq0v^vQk%(6jbZwT$;O2=?YH^tYyPU2OIKK)AjAZ^s)EGCQY@%sW7j+f6)hkzt- zUBKK>eh`ZDCMI!HN6ZSW#zZ`X?hzz%F^k>WbJOJ!%;1)R*(Bz0Ti|N6s<=iGR$uNa zfg906+Eiu}d$j7PXkTD&1V)RtqgGmtit;uzX9Utkw<_yp>DgNDC(k7KN**NBwxh}mL1D%Ok=Au4v0>f3!ea%0C$wL|Aw$7yEBw%1SRN3}z&3ngj zgOCNxG#3UqdJqqei|m?Oi%L3-b*e5Kl`T1?OPRVOu<;J3BsRs-Lz4Gut%h;}pY0W} z{-+P8&mkm^@`%uxi4C%Ww z|3nX7$EjWBW9e+wl|NN<-JMo57dec_2izgYjaN+-HGlWTcFL1|qf?<1xghKHk{u{w zom|o*Jsfn3t^Z!&`Y}x6wrAi6fy*bGa`Lyaz%@3Zk5>{f0HJSUJ}pWXe+7RBXZ9d| z=Sv^%@Tr%<%j*L^lWhac<3mcrxQmad(a!g1t?d$NW9APGKkfPJOCK0z(o`fyf*v1J z4}5~tw9qkfjG%3eTd!%4-}o9W;cV!hX`6IPpfNtheLCi7txJ8tyVleU>jeFk+Ci?( z?IXRJKAX<$;r#MGCN|TT_HbooW*?KA>8aVdJ>2*c(|!00llKRD)u#y(Fvgu{_&JYR z-e?+$yX~N1a*Dh$?%{K$PZHiSe8J=yoa29 zP!%{gMr^nDwPyt;pPInf4T1d1>Yl)*mxI6>U+VuPD2WmcEUmA>F37PsxlgfHP=mn^#mOE-2}Xi$nYVI4rE8MPktD5!%kaz zVZ>ol{XSjfv(Ov(IcATb6}{_s4kJ3I$3j#a6^tt9GG{``}|ulWH_+LTX|S4}Du;f>W1Wv%3)Wn|#nj zV&a1z;71wH>~5fituJ%uPVPDP+;iv8-(SB0oWdv|g>(*?B36(Us9aeS%d{&w?lTTq_u>#1H59&iOIevLFwt{4I}W?9B9#+2Sy z7`Y?HRlf7z@T@a?#wZw9+CL$_hh=wo>MsVuGALs^yoE*B!ChvWpb-<;tjzGOrU}}I zQ{>u5Q@ilQK1TJHp4@WQvE-H!WQ&sp${K0R`@%8Fw}r zBk4bo`^KUav~)cgcuSIfKM`D71UC}FRqQ5ou6$kSyqgH#T29rU8L)fTt~NXJ?3gO*OSnR FgMZd$xoH3Z diff --git a/use-api/target/classes/org/tzi/use/model/Operation.class b/use-api/target/classes/org/tzi/use/model/Operation.class deleted file mode 100644 index 0b536489562e3528d7e9bd640580dd101e366a53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1273 zcmaJ*<-d(WT0zkUPQ#O*QUFj7Lki~@=RvwqOFqc7U-h01pQ zmg?AhT@}bk`<_6)>9;-$Oza-XkJ9c)uWj!~f%e)B12bC2n8C;&D%r9yj&cc?%BY|! zaCuO%*E~{ABv5>&JsoWbjMP>R1g^j7d69P2fev-Eqc%Oyk7C+TV1|UpGKi#2Euju0 zbXr7yp_Z^UHFdd9LPYMIQf{54mAnq zcmFd7!y2BjPSu70PL{Ix-9!hOy{6=3QVeLwuSk zVD0<8z){=U455;4chzi2U_CAlyJo8&0_mzxesFBJBxmpXUfXXqZO0Gj4cYB7#eU&C zJy&^A1Gi{_ahfW}hduz8&dA(X;;-}qkk&gan7Cmy|Z;)(bRAFGea76-AY*A|#}$ttiSv-yCNN+a}(~c0l5Z z58?qNA|xL806q$F#x_lwx`LOT-SO->XXlK6{r>Tji1ui+Kq*S+$S^5GSwW>U`@L;- zY`1M4HP56I2+BTJt_pSqrK`0@o^DV+M+K8^k|}6Odu=QDsI0y(t*&m#j&R1V_gq&8A)zm54s7SP7uXh5_{tBY>qzTWYX?mGP%LQT zK)Ld;-)&0ojg9N9P&;;~VS9?tancChDd4Rf{QJ$oepbEu%Kyon)*5i3ErX-WO`ECK zu3kr_f2FdVz|5dIfJO%7a4FiE$c;E<;={-hhNHPzB*RV{)lgiz$89g1=)UL3mx}vU z9yfiH9Tv15_R8SK+M#?llU5zRl*_$z6IzBTELFM zQABs>E+PZm!^!}kK$JnOFhG56K)L$*fQt2v0hQ`yV?fhG)Cy>cCV@Idd71|P4AwGm z=0cVy5mL+o%=lTn3C0!7kO7HKKI zyo+k4$cE1t%I4pnK#~CsBg{rs7c#T4OhLNP^ROWc8n zi9$-_Le>(6JW3W)8W&yD7%XB3J`tGm z{4FE=*)iIIZ8W{Q-7xM3cBNqjfk45vn)cIXEgp@VFRWLV(XiYtV?Fd8cdIPHJ}qJ= zh6IMJkT0w4(5C0E*tQ)y4a0PTFtRKbF&tTXE!($3$8!S-Fj~Ye`FgD7+jqPmtaxtS zQM2Pk?2eoq_m$;4mKz2I?7?InpB3>r_6m$dv{Wd8oK>$2?3vxhceVP$u7%~f2h#V8 zBKAqgPkg)Sy|RZejRSccEMf+SNWGh7>_x*%j_ZVrM4p}7%;Si_?rzK_-?v`N9EWfi z2L$%6wcXHZ+M7<`R2%k^>w00FtiY@(ydQmv`;+ItH0oAp8J4m$mg{AKo$Jn) zYlUs!7BEt3UW#DeU$v!<`sGD>AE3ue%O@_S4oJ>+YqqiK+8f?&%Y99Ye9a1KR-NcG zTH8uIz45wb(>k|gngYX~-+FGjYf?6=kz+v#frDE2o1WuVyhgj}(tA+W5mRbLb@kNY z>hzP+YNt%1lot9B;ZCZ8BFBD0Eq975@)+5&!!%!ZPFcZW`YfPvMebGrfMu?J?62EU&$|J%ka=$CdSdj59%i11uo2*3Ds|5CI z)(RJNs8<3qp3)^Fo|-R5@w`qc>*IB;RXp{I&4%&P;t3qrrI|L1qt`keRp5vw z+Yg)sCgY^jGjZ-p{fykzd>q~B>@9unU2B!QdL?jvdlyemom3+zr^iz9$@h04yI8Ud zgWiC>_EIXI&Rne?3slls)kXdA=v75l)+|#OQzE{1yd}cO_e1Mm+ppQz9odJ5JB{VE zJg>M>BUtVE)AZaeuU<83p3e^ftJUHWWnA-W?WXO9Wz6uPo@T?}!8<=3AaIN$c|Xqk zfcymDbvAmQi{_>|F7bEbA%u;SIEB*>VBid0<^!DN3_k{x&$&K*_@$tHzU? zd|y6eB)NdEc)h@k4BiFrJ4$aLevMN6npc@TD9lA(i?IR9xWtjbH&|rIv~xb~d`#mU zYj~L;SF|97G)O5EWQibGwICyDkkgqU6@pyTf{dj>&SrvqOOWfh!K>8d8nqdas!`DV ziQh3XfP24jJOHVyTr5!j0vAAPI~m(1+Dfgz!!nTsZe}7*X%H_GvD^dk7EBGtLI%f0 zB3{lwyp5HJ<7y_Nj^kA#R(c@b!S@=DBN-g86Y)j{;u_W?jvJYXI*vDqc&i8EU2JMN zj%9FMA>wKV;ywHjalD_2sN=Xs#PuGCGkCztlJ)pEav0?OO6eW;m;S`z`|oh{E%M#R zLicf``#4rQ@fMo|k^IM28j@sO4C zC}LQOW2^eUk~CQIN!qG>lFc$lug-pub93Y$&z<93+&CUltrndJ%@%M6|*8T`Vr%yQwQ zGU#@dY2=Ag)o`tmYkga-EGUi(2}jB2P{PNH_yP0(mrs|<6ps$T)=;q{8u4K=pU@bf Pkg_#Ci%u?i=vcsiU65ma diff --git a/use-api/target/classes/org/tzi/use/repository/ClassRepo.class b/use-api/target/classes/org/tzi/use/repository/ClassRepo.class deleted file mode 100644 index f1861cd2f4f8a95834fbafe99b4f2c2ee92fe940..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 339 zcmbtQU1|a`5dNaAt6L~Nf+y%4Af-?WecB?pc!21pA=}-JB-x6-crPD3fQJ&3EsFT+ z!^|)P-`^aLyFGvpJSFHcjEz;~H=0@}$;zd1+8ev3&q_Eq4SRwIhL=+O393Y+XfiM5 z!Y3Fo@Q8Iws~h!WMJ-px{!$^lpxQLb6!UAs?|6!Y{{jr7T&qU-)=GwLb}PWMJILQU z@Htg&3R%(2$u1MWlFEJb&fhshnw!=x4ef!M%IhYuauzBmf9 z{;D+7A)R)nKcN34f1=apWMgCksXz3Cw7YkEd%Mr>-v0g1AAbSJU?+|~^lKQs)V+6XuZP%+A!7rB4^rhiRKQJn; z6L_v|OV21$&NQrSXGLJNp0!QiFG=sfsz`yw{5uBx)}C(^Le*khHx(xK1_o0t)py)d4~45}2EL6f*>*juO@T=fY5yrsEsW%}U^U zM~2xsU}TzsduVyGni3dL=m?DGEk{0W*2~h{Hff#}oOdgxy=!`wlG}>|!3&G`8C^y5 zpDoF2Mihc!QAwU(B7_%~OLzJ6Y^-F}9F~tqul9OBxq7AnSG$}(Q_Sg9nm64&*Q-NW zHp-S$jY7D=aLh(SrCwl=<wNmFwsbiyT`N}>)YM0L5{{ulgtI=mrWp1VC z%x$@TBy~frlnKmqx7U`b-sC`fU47R3Ek*fLlap!9tsc?4c*$*g75T_gjWzYo$hxDt z{-Q2EulkgQ(}|bj13b(L3vgDbkx9BjX^8Y5X+J6FF8^OqGDrpK;NlyIU&-|0KL2VP zn84TkD+5%(1Efd=R`HNV)ZrCMYHwumH)zKg{T-KIQH+|n8Zj}_Hjxf>z6re=qk(Vv zW%eL^tdYxN9Rs2Hx1{~l%_;Ls$GBGb6O%vOdW}!sVD?o@I7Z?%ZbjuU&d7J$a%hS( zmk&8Od*>LsqAOVDj*5APuz?SE4Aa!Qfhn%cVV3%H)LI~Ti7=Qn(TNe293C;$DU4$S zkIBu4+!J#5Lhd_qbiN(5;=bnzfjn2o(7&T$ep7?NZy7B}3LQwEb|Bfr7WFj+^fNMj OD2D%1sH)Pm4g3q%yraGV diff --git a/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class b/use-api/target/classes/org/tzi/use/rest/services/MClassRService.class deleted file mode 100644 index 263915a67031a004dfc2628aeb5f68f26748a465..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1530 zcmaJ>T~iZD6g?dx1LJ^-py0<6Q859vadllah(=acs}iw@V(E+3Oq$p_nMqA|(D+aG zUuc!3qE)*-?~k&)JqdBLy1ew~?R(BW_ul^Z>!-f~lyJvI1_KVV9`<06VgGZnC3qmh zI$zy*E`7r=xTr#9mKX-|g>@H07Qoht(25Z&Mo?)MF z8Li1?q?L){Hp5IGP~5xW2@h*obTN(z2ZuZy#w5d$G+aMzhS9n-_e4WJZ6rtxt_V_aj3`3hLtletgtx>r7l*3L=NUj8L6a*C7j>w4sWg<}|f@`hNsD@luT5SZf6o!!zRvOK4CCR#O+H7pb6vE3W ze!(}S2sPgnzAX(ddJlN1WuliVmNjylU8YKR-fJ~BWc)yodm>Sed=adRSlNB| zFl(ME!kha~mHmH>5`t?L*=dtuvC|U_$NIeVmma+vsT$$GsEB44+wCPxJ18*}(rIlq z0^Vrw%H42F1gciC?boxXW~DkNX)DWR>K7`Ls;Y;=v|@^L;Rmr7cjL8WBdSKN*q1BH z>U6LZ+D=oRw`ECH{nLzSBV!qvc2n|h4;OKQx<5mI6{C^*pXN)n8>IO+ng?j6kBi33 zwBs~0n)l3o0DDV|41TB4UW43Rq0#FY;3}@sj-f~=ndEVsoLQiS`HyfO&Ar3O{CgbS z##9FHG5r@tKI8P`u`?e~_$RsC#@P(MVEhfe8Ax!(kfrrF5t_gx{T?%zN-z&~{B|)3 z0gJd!*h|SvHiH|q7$l>c)JhDuaFNzFo=dc|)Ljd>jRgh^mJaH8Dk!%Lu$ 0) {\r", - " responseJson.forEach((useClass) => {\r", - " pm.expect(useClass).to.have.property('name_mclass');\r", - " pm.expect(useClass.attributes).to.be.an('array');\r", - " pm.expect(useClass.operations).to.be.an('array');\r", - " });\r", - " }\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/classes" - }, - "response": [] - }, - { - "name": "basic POST success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {\r", - " pm.response.to.have.status(201);\r", - "});\r", - "\r", - "pm.test(\"Response contains the created UseClass object\", function () {\r", - " const responseJson = pm.response.json();\r", - " pm.expect(responseJson).to.be.an('object');\r", - " pm.expect(responseJson).to.have.property('name_mclass');\r", - " pm.expect(responseJson).to.have.property('attributes').that.is.an('array');\r", - " pm.expect(responseJson).to.have.property('operations').that.is.an('array');\r", - "});\r", - "\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"name_mclass\": \"ExampleClass\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "basic POST fail", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Error message is returned for invalid model\", function () {\r", - " const responseText = pm.response.text(); // Fixed variable name\r", - " pm.expect(responseText).to.be.a('string');\r", - " pm.expect(responseText).to.include(\"A class must be named\"); // Updated error message\r", - "});\r", - "// Add a test to check the length of the response data\r", - "pm.test(\"Response data length is greater than 0\", function () {\r", - " const responseData = pm.response.text(); \r", - " pm.expect(responseData.length).to.be.greaterThan(0, \"Response data should not be empty\");\r", - "});\r", - "\r", - "pm.test(\"Response time is within an acceptable range\", function () {\r", - " pm.expect(pm.response.responseTime).to.be.below(1000);\r", - "});\r", - "\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "duplicate class", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Class name already exists\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "duplicate attribute", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Attribute creation failed!\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDoubleAttr\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "duplicate operation", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Operation creation failed!\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDupOperation\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n },\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "no attribute name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Modelelement without name\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoAttrName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "no operation name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Operation name is required!\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoOperationName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "POST performance", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "// Generate a unique name using an iteration counter and timestamp\r", - "let iter = pm.info.iteration || 0;\r", - "let uniqueName = `Class-${iter}-${Date.now()}`;\r", - "\r", - "pm.environment.set(\"uniqueName\", uniqueName);\r", - "\r", - "console.log(\"Generated unique name: \" + uniqueName);" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Response time is below 20ms\", function () {\r", - " pm.expect(pm.response.responseTime).to.be.below(20);\r", - "});\r", - "\r", - "pm.test(\"Response time is below 100ms\", function () {\r", - " pm.expect(pm.response.responseTime).to.be.below(100);\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"{{uniqueName}}\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - } - ] -} \ No newline at end of file diff --git a/use-api/target/maven-archiver/pom.properties b/use-api/target/maven-archiver/pom.properties deleted file mode 100644 index 4f8048af9..000000000 --- a/use-api/target/maven-archiver/pom.properties +++ /dev/null @@ -1,3 +0,0 @@ -artifactId=use-api -groupId=org.tzi.use -version=7.1.1 diff --git a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst deleted file mode 100644 index 34805f48f..000000000 --- a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ /dev/null @@ -1,11 +0,0 @@ -org\tzi\use\model\UseClass.class -org\tzi\use\OpenApiConfig.class -org\tzi\use\graphql\services\MClassGService.class -org\tzi\use\UseAPIApplication.class -org\tzi\use\rest\controller\RestApiController.class -org\tzi\use\model\Operation.class -org\tzi\use\graphql\services\MClassGService$MClassInput.class -org\tzi\use\MClassFacade.class -org\tzi\use\rest\services\MClassRService.class -org\tzi\use\model\Attribute.class -org\tzi\use\repository\ClassRepo.class diff --git a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst deleted file mode 100644 index 5cab6737d..000000000 --- a/use-api/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ /dev/null @@ -1,12 +0,0 @@ -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\graphql\services\MClassGService.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\repository\AttributeRepo.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\repository\ClassRepo.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\UseAPIApplication.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\repository\OperationRepo.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\MClassFacade.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\model\Operation.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\rest\controller\RestApiController.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\rest\services\MClassRService.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\model\UseClass.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\model\Attribute.java -D:\Programming\use_web_api\use\use-api\src\main\java\org\tzi\use\OpenApiConfig.java diff --git a/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst deleted file mode 100644 index 37c3a61e1..000000000 --- a/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ /dev/null @@ -1 +0,0 @@ -org\tzi\use\RestApiControllerTest.class diff --git a/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst deleted file mode 100644 index 57b820809..000000000 --- a/use-api/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst +++ /dev/null @@ -1 +0,0 @@ -D:\Programming\use_web_api\use\use-api\src\test\java\org\tzi\use\RestApiControllerTest.java diff --git a/use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream b/use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream deleted file mode 100644 index e9d92f176..000000000 --- a/use-api/target/surefire-reports/2025-01-20T09-17-37_242.dumpstream +++ /dev/null @@ -1,5 +0,0 @@ -# Created at 2025-01-20T09:17:37.416 -Boot Manifest-JAR contains absolute paths in classpath 'D:\Programming\use_web_api\use\use-api\target\test-classes' -Hint: -Djdk.net.URLClassPath.disableClassPathURLCheck=true -'other' has different root - diff --git a/use-api/target/test-classes/org/tzi/use/RestApiControllerTest.class b/use-api/target/test-classes/org/tzi/use/RestApiControllerTest.class deleted file mode 100644 index aa928655fb58d279c790e89fe6f727c159e416d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 312 zcmaiv!AiqG5QhIrlg6gi6py`?Uets804+i(^b{=A()%VZb;~weHX9GVl_$Z25737a zXNyO{8TfbpZ(x@H^!@n-V2)vi2%Qx1013K;;atr|Z+>V>Vnv&Ja5VL*r%_E{0~Lf7iCJ(SF4X_#CWwvuKmoeusN z#{NY&gh}!5EWPxw@_{2j389Zhc63OYd72Hbz=3vnNOJr{s(%`VQ9`yxiJ5hM zV{HQp;(iD}M#}tPq~O6rm^lLN%^j@&HP9bYEDxk$z*2UOW`B^l$GMkqcDMM06yO&r z7blZHNZwD)UwHSD|MwUP|BHr`iKDB9k%`kEj6Hs!YGY??@~7#*c_8m-VsGbU;cVyl z>JLWH|DojM{0DJ@--#R9**ZJgSzDVp{y`J}cbdPMg@>+y0oDWGhqDdPR^RB}h>^2} zo$W7%9(p+{Sm8fjZUb~R`IGRIe+q-YUq-OMF#g>W9$F#$vm#iT0ciij>3&36k{GSl z8kAB!10)1Q0u%%UHW&bCZ*Og31iZf?Mtes)dlN@z3lpcHXg=FcWT<^g;yj!^^535W~pWgzkWx1A+anf26W%lUhQ~M~ zu+F(NHB3gAt@(*++futWC&M+}7uX*3sUc&E%+ki8j48mBtcL$N)%PGnqf*(L1jp2e~d9N$l7}zZHow=j>^@ zD)tG5{W7@WI8sm2`bp)TGbOB87{HeW;##p^_ZqAHW=-B9VoX zDTry^jDwF+kxLXpByPL)AwDjz7(K6J-!{fGX4a|$cJfk;JNSc;-!xfM^Rsp@q5_`I zxc1i@IHx7O8C{xO(w+>lb^Klw&@Hm(r;oIME>ZcURX%oF|KSu+FA-hDFpE4w)vnVZ-E z8UOvOQ<_2}QU^2UBJ@SD1olmk?bYB}bO$brs%Qr~Oxf zozK5eA(z0&hHT>-JaVy<(zsjH7qS||Yux+9kiRY*!qeBKX+W#kULxe(Gm;nowfyJ_ z&|O6%fMWr{v9<0G|%xHA~Nv^84 z@`4)LZ6rz`uA+Wjj)n3B+62B}R*s|;Mq^cA+)CGreB+lAMBEk6jgXBA#kmb*uJd@= z*-ThFg}q<+sN{Q)<1MWC3O~)MY@FYz^-#OJb^8w4hQu)`L0kZo=w%ket?-!kGvQ9q z=Db^Zwz|t29%nt1FbL@HxE`Ta!kv0E%>tJOlzi!;+)_T=_QiCuQY#`ca@%RYt<+)p zlZFfZvQGu!p%c2ctG1spu2Tu+U6H0TDabPy!%f@0Mw_WnLVv4|c<@aPIbxCDdQM7& zGqeSdY4@qg`{WrGbjwieGkOc;nNejwW$rwO5E2T}^#owHLcPI6_r;`UA#tLMXV3>4 ziO!=ZMTUuNar|Twnitn%y@1lk=hr3%&s9z~yZKyAnpGD+KMOtd2Rbj5HYNagrDk{` zEefdAVx=61;$4wL2fN$pYvxN381``FvfV0TsV*)EL752SGTp8hrenp9`}L|Wb#L($ zD^m#vE3t@>gN-{WtDfrM(u213T0dypEYG1ZJ~2FV8_XV$|CG&jdm)+@yg>z3K%7kf zJ-O?^I{_~b>E>!!WdB*1Ky=w|NdQl0nsUdnnIUt^Qh|hBSX_y7 zhX_UZPj}8ytN`jfFWvp^^<%Wh)lClhC+h?^8Y|QJ>d_2u#gSxG9{b8LVh}64>)w?~` zUJip?vxD2EDBNteZQ~B|@4>xVM?=gB4sIcM2nd${zu^86&}k}G@=wGu`Jf+#?b;Cg zjRoeRI6SQ;F-~ERQo?xLi-;bRR+H%xCqHF?YC7R%;+hb8U8qJXl%q5?dZVbiKLo|` z2F6dVlE-axsQxV7!|nEF|7ID&QiI+ABH)oDqa5%x@cT3UFX^M5rDvT3R^!tE;bYb~ zcRyg6j>QH`cvFCX7^w~@S;B?yM$O%Vw5fFMaQ?}%bf8wEP4vs*hSAvdIY(2r^@Sd9 zlC{^FAGZVw%^9M(m7eH%;V3h#v5OIeH*f`10+huG4eZrSW(zL(JLep8fy$EA-KH!%p((Y-MIZuU#vurjQl1jH=W*_>#?l^+-59=*86pEah55tE-V zDKVZc!I#I;^$hudi=;ETCRGRv6i4l`exuCDsBMgi++7{sk>ksv!-CZ~U|;Jw+b;Mv zz%|#Ts(EkCDh|&PQ9u8y&OX&ZsD257o?)FDe}ij0_TjXoJ}4Rl=ssrGK>upivW841 z`Ek=bjLza)T6d~mEP1>2XWRy5=I8OMONBPo=$PqXp3oG|{X?im5Vog?xDXHO~)0)-Y&;TGghUTGlLbcV;Eef}r7&e~UCzLL`UN zaCItMp{VaHh_vHKaZ67eCnHRRGw4E}8pDkS5LCGD>Q?>%!kGauxr;JJWKwGM7G>fZ zllFT$rB$@+us6^h+1h=RFjb%*zYWkVkAaOV{^*N=ZSoUiS!45|HA(}sr{%2fE$s{) zPeypAIZ{*XYYy=`i9Aw;UCkyO>+vjucWSylrSsW7>OMK)`?L()RrpAmKB156@vJh$ ziM{2Wg9UPK-l4P6lNq=J)E@UGB#wFMxX!o}u6UMjqWT?fNn}i)<95#8KX#wF;`JgL zvzMVoX769k%=I!R0o92u_p*O=O|-@0E$1=i2+vQt{$+!4zr=ppf>#RwN1-)13ZFiR z!XHbh7|;l4Z1N-IB2=~QFvKx$DP37Z_(b#la zuv9hatFZa>zOX7*IVh-t5K^4lpBkq3T^m1urORy|r#kaggTBu)9;mNZkEf~P7N#c5 z93$~|msV{tRCgfXdG-d1#j^vgnpUcT;cl)gc>0N?li7e)xdCRF*!;1?_Sz!^f-Vw} zpj69BjB?E;EfTiXMrplkJM(T~O6VHG8bLOc5pKRC&lKRMrigaJg%$wM)0CLv7|QHt zM9>Q>x1v07n28A8%2b4R(s!b;H1;$DIkk%hWZ#eBmNl_L*&Y4OFx#(mSqW1)X)_6( zt0aW0f{vCOH5yG2suIeqs@xo%jOMLcDhAgFtW->^s6i>GqoB6Lx<2NQD_!zK_H4e1 z%@Y0v$Iu?%hY@qMzL&&31Jx)OI(lNg2HByv^R{50=S_9FP&g5&BYYYjeixn6tLkUP zutO)eS8jWu?YEK{ayO%fm{k)wDd&GbAN%Rtu3RzDrs6} zI#X2>SyN>4kmN`TEeWozV~tP(G9P*xQgS2mPKeTkZ$e^SI_IU_Ww7&iPqn@E$6J))?z>S>-yJ)-6M zJehQSO7^QLASp32#X$*I1)%>OU@(_Kv&>0PvgJ92hKnVZG{YSC!fl#!+VpYY=kv&# z#@iF$?Hf7y*d+irURrbPX#4HaM+^7UR~>@JTQvA^8ttggk5EP_IZw1^wED#1 zhO@^J>P-tPdVnh6OC;sl=tf!dyog|EXm2>>%+z+Tchqh<|oSX_3KFl?f!dBS)u z^H--E!9zv*dZN>H-`c836}KFUY(rwt3#k=C!3(jn^X@e(<2?8#X^JM~YiAjr(BdjLRTE1gmvXk!?6d*r$dTsAY}? z$C6Ef_B2ESnLkdk*pLBQ{>ZGElB|~LWKU$?)5}PUfV_GfHG3cuX??G6e_-o{Z&%f0 zcf&FCXx1;^E8Z7G=W?wam7UTapekR+&c?kEY6?WlK1!yO1UG9Z!Jm6;?iWfdRPzox41s zmitiyyk~bDnZgy+0KpQg@KrYFh*qa9i7YNAyv4>xF8BP(F+Uuoo48Az5 z9RR%Z4wGlaQ)=G$BaD+4r;v|{YWerdjY}ad)u{B@e!3OarD74@WD_4vb(=aMP-@-FD#-`Zei^e!Dmcf39 zEz}5Pvsu^&sxpT|srlRxfb7VGj+_N=D)L=kJ?a(2L9j1>1$zX{Dg1Ce%Wy+3iy{i) z7Y3k-WgBto82MO9IOLbDx79PfR?Y#xKIPvpBWt(AHL_qoy!fwvC=WhL`EjiBuct9D zWiR>37r1wev&eK#lZdaI3JlhgKo}9B$s~e+Xk&D;hAsiS-RF;{T`hPbylG|GDQ{Qd z4}|eD8WSFAlF07WH}bb8e%YQB@bS5UD~nh#S!Y%hYVn5(1t5EmeICc@4$fRJ-S6XH zChB`3GH`}_q`Q1Eq+mxB66JpuH1io=@m-Ui^rVcM!Zg8!Fbx5+^7}aZ0)JXdK%)5T zo4x2NGSC{^MuB-4FspnTSa)l>B{~pKh*fB-Z|jjxgg5sF7zq<4iiRksCxj(7QAx4v zqy@-L4^MxhJ{eK%pucV!TxjsVI-W`&Ww8{ngtRuJdS0{TCi3q4^ZFt2;82*vd7STp zMIfp|wg?AB-N@6Em`k)TJ&io~{ufa^aiTLzP_67zEY{aR!P|sPW~4# zO(r?ijjzt&XKOKSk{4ce(Bp#UxafdmjsA-7EJoRtxUGzzPxcwsL{Dgv(FJPq^-4Tv zQR-IeIMKU{!n7LBCQawRG38VgDty-k|UK2 zwO+I6!5J7A`RYQE)~WjInaRB`s^I&*=ml?S#LBe%!<89vbFt4s8beK^d@9W<$?8u8wv03X*O zYP38$n{m!o6p_Z!0AJw9=hBy7wGInEy&BPXtQ>7lugAEIoUx)VW1|?#>Qh)Jv2o2- zc(bcy{Uk_k`5Twudj@HWAuH+UX#A*z+pwbah6TR0Qq-U6>mx|5-7=8rjJcXOUdqiH z_o-WXz@{2;@%YpwQ`;haw+C;#S?%9zFmb+AZT zYb)eHu_h{^sJb&vq7`QI86_ zQg`RGaFdn3gc*c~W@XuzrgIF!;jm9$Y7lKOeucjs4U3)`kIyubq&!OD#kBoOG($Hh z`KaLtI;qX$B@q#CyQ&UZqNOi>+K`!NIL1Y4X1`1Eq+39-EIwXDe)w{`_at))BFzdC zA$0C61koDEox~o4h+;&xVuZ%(^QBdpdV!nbz8*z}6+V!nMhfjCy#H~txrYZ`bQLw{X%dT&p6gP>7YaqtZTG`455-|Pf)H&V!YxF8pi3`6wIror3sUo*Z%(HjmWha z8^m;EBo~s}v<2S~j7O41YBjk+WS8P{<2Io!+g6gWVv3mg)C?^j~PUXL#&d5n{isYurtxP zXzGTVbr&yB2|Djc@riRdoj34gwoe>d@;n|Ma^q=i^}ahtgg|*O*A5fMOFjAmmJ)G@ zu-r&YnG&Oci12XsagrxlPMIBI+;kx!YAKqA3U}sd(YyLpXP-V3BkH$Ory@e{KB?%+ z8E|06>~Cmxoxo$~z8(suHMIz~SiNS^sPO_K&oWE^T(ca+R+!s~c%rIYB&wAIX zqZNG^$qco_k)x8JnMppqgb6Z*!(8nSqcKMx8e<-=sS18 zLZfkPe3=3bU>g6v(N$X134)AUeMmJfH>2N_1Cft5%2D{BB1)^9YvE1l%I&MSICOx9 z2p@;!(_!?5kOX>RNT)`#e2@?NgdG4*i0zy1Djo)nU;JV!PNo4t;n`fjdxnW(X>41> zFwf>Zrn~eLL6jSnE**StNtV^u5r(F2k2+2g1&0Ng6b7D2&2DM)uxrOrcAOqlzgFEe zEnTa^^@=NeZ91f3J@HB4{NwzBAUen@KkS9Q-)olWny{&Ugel+Lx<<{8Y@M|W9eb!U zpRaO8`go1inhVA4!UqSWb-^oP>X5st-_2K{RnmRnk5B|C4Ul$?AsIW_=abPPXRJi8 z-GOGnM>E3Vi!bb29&tuH4z@vk;;@I`n+BpEdcY+Z%(Z#FG%$d@=0>6!6F-=3!+3d# zCqbx&-dSw+Nc#%<@26THXKmOA!TzQUE_qNs@Vj5CfB#y3l)%-%AMTecuV~rv0?jK$ zD;qmh`~W5mx)@Wc{ewjN3M5B=Louc1++x*i#?l}v>PlvpHNVh7Ei_x_6Vs&>x8^h^ z2>ye|WQH2JMSXXcmZ{`)Q9TxR-$MAMS3l)-vxotXo6oUTLbb-#YZB|DSWH(|rwL0+ zr$$1hZgD-{3B44IFNmk9AX()O=ioC<%F~+a;8bJ1rig;#y@0=9#cL>(A(5Wvo_n`PJ@XYtY6tZKra|C;~dk-dC8(($T%YPls@vFySFM1hv6y zG21_;16A|URRa89LF2^%TH0HCGvGx5MW#GZQ=a#YKXiMtxH}LXo zcDCZn0{j;G3%&fLA`SN#fXAc$1qB(0P*jMNCmLu(5&^*E9_SLeYw8 z4K`cLdWVtR9+C`O%*Hb?46v<-g7@vMg61gQI)RpHUD5~_vIDZ{vv?Id+)IB#khsMcE-Pfbd~pEA3>61| z_cM^l`d(Vxy2U&1@s| z;+vRv5Q$68aWEXHDy6|%2_T)XForAhJSeN7ZS2Dw5Z57xDV=l21l_g{Mjq=M4A#toqj15O-EQv_ zsfkzD#^Px+G0rkdZ029Z-rVRkoK2X#PBb3Q7Xhuex$Y-~_2SzfHW}(=5p^~zm!F9w zC+6z!=Gn)0I6Of~a|c1vW>7xo?4pB5pO06lE1Wbf;;YiMGY0JJl{`&i)!{)+@{87X zk{cD3$L37Ed#^T8|1DK1pIdn^)2Q>KXFMTkfiCyL9V%=X)jmX8{Y5%k?Nbrmf+yCw z;lLwvkCH}wk&pw4j1zAu#p{nb92$=bxh+DJ#sG9{n7}lvC!@1D#>9My`-6VOL8^_ zsD-fVsh2!9AQF+M#scU*43&Sk$UzbGh+>o{t{9j$O)vW$Ia`H&S&1tDNn7jRGe{i$ zs0#%+gIvNwKrsF;gFGkzD*d|v`0sUHMcWC36Z3YRYtDEMjTuq4?yY@gEOzdO7QqC* zuy67+X50xHrtk_iop$$`${6U)j02`E8ThxZc^k<@-S$;WFv7$KWigS?jLU9}SEq{t zcaZPb^1=u}1nYbNqd?%OQ90vF>MZQm%1aG65YSjrbby`(5I;c2D8{ncc2b7?w9`4Y zs_s?kOLb|z4?#j;=Y5@LeBdvFM0S-3NR+;PXUk(d@J3*a)vGkl&7GjrR)%Z#Gmr@h zkSjPPV%b?OGp$PO0$S0_W@3|pDWK;mSEH132UOnnPNy(6)f8wtu!PXSU-5YcTY#YT z#d^vbDTZyv6Qbq??+hzcP6cwxfRC}NX&db!;0Xzi>~Y0$L-hmNm>cr4Hm8OQ(_@5HkQHDT|l zBrEHiK6`1x;Pd?eV}zB9gKFxH2BuU1;sK&a5X91sm{|2j=!E67xGCz;h_ZtM+Qf;% zoyhLW1hk-hhois`Qs@>fl>Y2jhJ(K9jg;PnkLSp1FSM*1Uv;QQH!a$H7+7y1K7;9q zf<`ZWEu#6naVSLqvpeOuwOX9U--@l`Ii=B>uoL0D1vPHZ6EPV1uUWC(uC+*cgerIg z0n>}FeG4{vtym>t3eR??=Mwl)=uTL2YxItLk ztO|9s8SX0f(Q}=lI6+&+@vkRX2W*V_a&*qI(h(l(LvUJ2cTYy_oP25=)@VNRNwjT?q2rgxrf<2FY%Fw;*-&&rRy zie62GLc<1H;+a=DVtc6j2zeSPH)S!^t6)X{V00^=mM{3TSyXF(XWAl#<}e3lY;1B` zz1?W@S@PWV$>^XuM8aWqC<%a0!i3ph5%i6%Wz;2Bo53slP==ikG~Ng@c_|I(yb#hA ze7oATTjjiOCVZxwDd5%&Vx*BqiEeOhw|q@y zKBx7c{4e?)|5E_}AN;|v2|$gT>Xg*vTD3@@k6AjT+Pv$b}k*r40XPRw$& z4F#PE>Z@Xrm;OLD{Sd14*O9yU>AOt`Mt0+uuMGt8S@yMCOc3*PR>(VLKA9~nq35-H zLq7uThp^}2Dq+`4er8wY8j=VCSf#|gIu9? zr3U-~u%8U-zSoE;YU;Ky;gOavf)(kn+8?ZR5iL}0mMucz zK{-;TQP`Y0=$#YeG)~KvDdWQwS;&q-Fn613YPR+1ojg_@9+vxcn#C;io6GgrvDvc< znFeeDqh%sR3|OikF?k2xMfP?z=)DD1+wCJZKQ8lMJJMZ>+s$9dCDgwm6nGh}h;U3& z>ngK4qH66ix=*fSCXP3)=iGIN0V084z`o2iv3;vbW}s}Us<#b^0#kj<1ETAdl5al) z;J_743=`3QW_<=kIEsaewKK$b(b{Hbdn+CaZ_qm4iDo;&g>Nml0*%j>359(~GHg^A z6h-=ZA&0@lLYC$>vb>ki;~4^nq+lfrkwwKh7sMf=+#Aq$MbeOus->;uUe}jI2>DRQ zI`1C~zLC#Zd( zblm}2dh6GLcH8wWO$D`COcW{)!6mZAj9K1}9r3f;7CS=Z$~Fgo{sA8CK4uH?4uRaH zPdXML7DX8EtZ(w>{T8aZCvKOrDmcm9Bdm;OY|H~2p@MW0lt z<_0ELGYAd>BJ4Q?#4~WF_)SmXebb$ri6OY}j`5$LGFm#>+3srF*e!4YZa-Zkr8&GH z)Y;*(9jm6}cvtHJ{b<&;&LtxuOW8X2&{R5|KA)lD`iyL&wrOfux|Y#G=Us$xbQbjy z2}NGOeB|nJDRX+Ppp98?UARcG&;XMcYD0M5BDXc4)%;bYlXKlN_e<9%ALnm1r;Rl` z1OhxMyQC-QSg+=Sr%GN3Gpv1e7>D(NF2(_7f^dIndk6LV=2$+B+zyA%xD~d z==^=_2ZE!#dMg+_a(X+^X-1`8F%S!qhH`khxUHWOaiB)bkJzK)u zq8lh|UwqbZnrG3-aEOl>78ABx=?!(rQJ`1bR%piF7N=E?-ve?EF}yD)Lt+3Aqeom+ z^)ZI}%kXm+hi|3}vt)~bJ5y+ta&R`um2gr}s0z~9;{LruN*!Ov`6~^Fdtojw`*GXL zybX;b!kT6jYSE=PS`;HbRLQd?he4vdw2sqZf2IXlm|cqB$>HI}c*)zZUPwi}DM%k{ zxIOFaJq}M9H~MJwcqRkUz&X%O`)e-(@KAz$+a*)v8lYQt&OtRdInCpY_chI;bEoET z?^JcZuNMXR5vdSLPxjRtRzl1MMCw*4gJiDQnv`$D=b>zw7-2a_+7m98kW87_ zg1?={)Adm*;wc5>S60F+^v%!ex#eF*?cX{^_iHocS5JJ;Cd9#zdW;^c;;}|5)xjW3 z#jrK(KIuTonVHkZAdZv{BUtUb1B*o?gSL1WR-R?DKnH{!lQ-(t@F-RsIOP0BfwY1| zLsHB{1%nTBz&(tKOIc1zn1_X!SDj4E0o|tLrVFpVKQ`;uzfgIsPlTaf>13wKbH`-# zT1Y|eecX3fMoHpI*j8q7la2`19hbP0PWpji-CM9~Palt8 zAU*CnlST%#9XhhyLDKXivof4ZcC(6y?CZXB4d{Q=D&1430r^?IP+ae^N5ar~ILbcK zE3w6N3(C36o%QZP9)w;KCIqDH5ONT^i`8D_`PX9APs2mBY*F>!7268{qfSn5*)!=o z)Ntp>URXhrRlcc)s+@IvA0#2S*5xt>%K1L%7x-0Bn6+>gQ-zmSDTj23bqi^}yUE2{ zEcbY?W9O-A0+G7M;&qd>TY9kD2EUy-zq6}wC$+&`b-Uj4iZyml7l~wUiL}kGVLbS_ zs}Y6n!*xTE)KI5MfWyG?L~yEY4Y?a(tQ6ifo$klBgN55Q_LDwtgRFOzRpw)b<&o9GDBGESphFzPto)4>^ z4S;KE<~g8>p-1&aem7>?wPq8j`vGBxLUE-L0xL?naQ5|1uX^_`Lnh=3qrEBTyP}t! zrNqjgOQo7d1))k%%v!2E)J*aMp{=>)tO_ZWgP^lbVxHH@<9O00Gr_Q6OeU^Oq_XT< zi{SOf7B{QCSF*mr)=Z$WUZ0n?(|H4%9*}g_I~kNPL+TfJq;ho#4IJ{PE}KKER69^I zH$`TWZj+AQuwBg!OeClMSRrfp6b87bH>?av&p04re)TNMWc4fIl3Ry7g4ATK45{Ka z%0{ec(HRs*=9w0JkGdKcy%qv zA_+$hW!pq|+(rtQ3kh&4EbcIAQY!sd#Ke=^-&M`7+CS0uo;SIzNk4k8eXt;UK0hLA zb1v|6VRH~=*Rse7nHB;+Z*~$xK+u90wguq1CVYPQVWwm|@xGAONj^tQ8gs01HB2qQxJ3@{1&Kgg{Utd3Z zRZ4`Kdoau`-Rwb1ZgMeY?%zWeway}K&fkjfb-8PHcd{kx?EcuXJ%L>9X`9olXIj+V zOaa85XXN5ZpI-{1VH~e?eyDAyV+WbY$v0if59*XsEcTVC(N%FzKAt>$`S{x5>XwW? z8kn)Ew8~4F(3F#?B;RVrqNX(|2;0QirA28vHp2xon%(ye+mT+PG;4Q>1UqzTRijxt zODKlfoR?F@YdeY%TY$Vgaytte3f5Y;UF$>QO z>N|%#&j^B6^EmDjcUeevQ_GXswC_9L&&FH!j@azO6hzJu)n@e_KdFuqin-B!6~XYJ zJW&Y3`l{AokL-lCRtPvV@~kV6$BM0Q^E_0)G$(mQ%cpLC3D?3|qYId0b-Q=+8KiV3F}GY9@`9yp51Qp#qKEVSK3v)ygY!WTBd$og5zCL~~uG zohe@-kulE#vh}g~HaE{VkBGb|;PSDS_|fxW57g5{4*U1Xv-RX%GF-`%%N_*Nx=o&= ziRGRnk9(m#&H5Vjw~#|zQY4Z4-ZVD`;(3>P1lG^I<-78KQdPL|&U!9ys6Y#ot;(1@ zS1Q-IANx7!TsZlBW2w6xh0fG8-Nz6vu@4Q$N@V?SyF@Q)3^=K;UO)1MQ?z$T7NT@} zXX_Z`hvX}4p5m`<#`rEetd5v}7|V~X_S1WAr{Po_?=M$Ny^apsiwQ-`*IUDVgerM6 zZw{sKwlBPwZJj`qj64iu5P8>=n~&(R0L3N{Uid*P{XE=E;nBi{lYr9L))!tP+<-*0 zEqH`B)3LgW(^Zr(0gTn{ZSU5p(4;rEGj^c4^rsp{O_HeHKMPWVPp3YTIhT5E>31z?igj*R%Z%?AwlhC|wSTaVA zKX!%|T0TA3VuR;aYvQ34@NqKI6~f9dCPqo9&aSUxw4b)~0)j-74iFprS%|TzlIoo> zs{~2HEODB~mhk)T$LyJHm2tSJGjpZlk2K)JUMaR*b9X&UFkr_^w9w+iRjZRr2vSMc zLSrhhJ|3ur4S~PoEfac~db`_DdXH-VBN8ifzElrU2%j3L2eo4oh)x~FDXr5)n4@6-J@uNkR3qZs(NnOcZlxsJM^~+!MEHZpaiKm?G={@)e#D!V*@358w9MAdxjXSH zCSM^bUe*sNg@v*mA6pNf08Rj}>cKoXNGMF`|IXP14+VUoLF@|Nzy4=bKh%D(i|&X2 zki&N`e1GNmQGx&ekJ>MczF!SLpdm!$91nY z27Y@_qxh4?-|ZazTjK{|@8`5Uv~y3{`*Gdd!3Ed9ex+;t$=*GM@295F1I_>C9`7lA zKM|b&3&MX+ivKj2dydjis1FaI{v!PS_i4Ci>HO4RexUzL3Gh#YxTgUA1i=K?v45RQ zM{uF+k6++DCGe-Z@bA=rsk{AYAomo(pGaQ6L;CHkK6KrC%HU6&YB0_}j|2X8OApC? z_Y}gP0GnWd|3uGUgufcPuM?^ty|G4{am{!fnGulm2^mHpJG2OsGC6><+)X1{{mNB={5 z)=v;xa5wp{9{V4_zbLl<7g_6}sfT2dpQhlE|G!NAC<{G=f7k{86F%b6-{Jq+6aNtF zVN32$EE#Za`E^!)+o1ap?qO%;Pq>d@m-;8%gFefLa1Wc~e!>}mGuJ=iz$gB{w8}k1 zd)Q_36U_u1bHAefrsw7%*u&O|pJ0pN{QfK0FIn_KBgI3^hy4dXF~5P?4u8k|pSlqq z8hBWq{Aqv@oGkuf;6KUohadgDSosk9VI}4#b_Te$6t WSa6<$fFK3`TLBlkD(*L#5dRNPyTKp; From b46bd05dfe8a5da3150fe836f331d815cb0ee120 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 25 Sep 2025 18:33:46 +0200 Subject: [PATCH 042/148] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0d379eafe..0f45160a7 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,4 @@ fabric.properties /use-assembly/target **/.DS_Store +/.idea From abd705c5dde73d673e57c98e14842fcd02affb0e Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 25 Sep 2025 22:44:41 +0200 Subject: [PATCH 043/148] Comment out test data initialization in UseAPIApplication --- .gitignore | 1 + .../java/org/tzi/use/UseAPIApplication.java | 22 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 0f45160a7..03bbe636e 100644 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,4 @@ fabric.properties **/.DS_Store /.idea +/use-api/target diff --git a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java index f87877fcc..c14b07f99 100644 --- a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java +++ b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java @@ -15,15 +15,15 @@ public static void main(String[] args) { SpringApplication.run(UseAPIApplication.class, args); } - @Bean - ApplicationRunner init(ClassRepo classRepo) { - return args -> { - Attribute name = new Attribute("name","String"); - Operation operation = new Operation("operation()"); - - UseClass mclass2 = classRepo.save(new UseClass("TestClass2",name, operation)); - - - }; - } +// @Bean +// ApplicationRunner init(ClassRepo classRepo) { +// return args -> { +// Attribute name = new Attribute("name","String"); +// Operation operation = new Operation("operation()"); +// +// UseClass mclass2 = classRepo.save(new UseClass("TestClass2",name, operation)); +// +// +// }; +// } } From f81b78b42558d1433211f88a4aa6f85d6eb0e5e5 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 25 Sep 2025 22:48:37 +0200 Subject: [PATCH 044/148] renaming to DTO instead of model --- .../org/tzi/use/{model => DTO}/Attribute.java | 10 +++---- .../UseClass.java => DTO/ClassDTO.java} | 26 +++++++++---------- .../org/tzi/use/{model => DTO}/Invariant.java | 2 +- .../org/tzi/use/{model => DTO}/Operation.java | 10 +++---- .../PrePostConditionDTO.java} | 8 +++--- .../main/java/org/tzi/use/MClassFacade.java | 8 +++--- .../java/org/tzi/use/UseAPIApplication.java | 9 ++----- .../org/tzi/use/repository/ClassRepo.java | 5 ++-- .../rest/controller/RestApiController.java | 10 +++---- .../tzi/use/rest/services/MClassRService.java | 12 ++++----- .../org/tzi/use/RestApiControllerTest.java | 10 +++---- 11 files changed, 52 insertions(+), 58 deletions(-) rename use-api/src/main/java/org/tzi/use/{model => DTO}/Attribute.java (82%) rename use-api/src/main/java/org/tzi/use/{model/UseClass.java => DTO/ClassDTO.java} (77%) rename use-api/src/main/java/org/tzi/use/{model => DTO}/Invariant.java (96%) rename use-api/src/main/java/org/tzi/use/{model => DTO}/Operation.java (82%) rename use-api/src/main/java/org/tzi/use/{model/PrePostCondition.java => DTO/PrePostConditionDTO.java} (83%) diff --git a/use-api/src/main/java/org/tzi/use/model/Attribute.java b/use-api/src/main/java/org/tzi/use/DTO/Attribute.java similarity index 82% rename from use-api/src/main/java/org/tzi/use/model/Attribute.java rename to use-api/src/main/java/org/tzi/use/DTO/Attribute.java index 687a86920..a6da6278a 100644 --- a/use-api/src/main/java/org/tzi/use/model/Attribute.java +++ b/use-api/src/main/java/org/tzi/use/DTO/Attribute.java @@ -1,4 +1,4 @@ -package org.tzi.use.model; +package org.tzi.use.DTO; import jakarta.persistence.*; import org.springframework.data.mongodb.core.mapping.Document; @@ -12,7 +12,7 @@ public class Attribute { // @ManyToOne // @JoinColumn(name = "name_mclass", nullable = false) -// private UseClass mclass; +// private ClassDTO mclass; // Getters and Setters @@ -33,11 +33,11 @@ public void setType(String type) { this.type = type; } -// public UseClass getMclass() { +// public ClassDTO getMclass() { // return mclass; // } // -// public void setMclass(UseClass mclass) { +// public void setMclass(ClassDTO mclass) { // this.mclass = mclass; // } @@ -47,7 +47,7 @@ public Attribute(String name_attr, String type){ this.type = type; } - public Attribute(String name, String string, UseClass mclass) { + public Attribute(String name, String string, ClassDTO mclass) { this.name_attr = name; this.type = string; // this.mclass = mclass; diff --git a/use-api/src/main/java/org/tzi/use/model/UseClass.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java similarity index 77% rename from use-api/src/main/java/org/tzi/use/model/UseClass.java rename to use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index af3059c8c..ba0477752 100644 --- a/use-api/src/main/java/org/tzi/use/model/UseClass.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -1,4 +1,4 @@ -package org.tzi.use.model; +package org.tzi.use.DTO; import jakarta.persistence.*; import org.springframework.data.annotation.Id; @@ -8,7 +8,7 @@ import java.util.List; @Document -public class UseClass { +public class ClassDTO { @Id private String name_mclass; @@ -23,7 +23,7 @@ public class UseClass { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "mClass_id") - private List prePostConditions = new ArrayList<>(); + private List prePostConditionDTOS = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "mClass_id") @@ -42,8 +42,8 @@ public List getOperations() { return operations; } - public List getPrePostConditions() { - return prePostConditions; + public List getPrePostConditions() { + return prePostConditionDTOS; } public List getInvariants() { @@ -66,12 +66,12 @@ public void removeOperation(Operation operation) { operations.remove(operation); } - public void addPrePostCondition(PrePostCondition condition) { - prePostConditions.add(condition); + public void addPrePostCondition(PrePostConditionDTO condition) { + prePostConditionDTOS.add(condition); } - public void removePrePostCondition(PrePostCondition condition) { - prePostConditions.remove(condition); + public void removePrePostCondition(PrePostConditionDTO condition) { + prePostConditionDTOS.remove(condition); } public void addInvariant(Invariant invariant) { @@ -85,19 +85,19 @@ public void removeInvariant(Invariant invariant) { //Constructors - public UseClass(String name_mclass, List attributes, List operations) { + public ClassDTO(String name_mclass, List attributes, List operations) { this.name_mclass = name_mclass; this.attributes = attributes; this.operations = operations; } - public UseClass(String name_mclass, Attribute attributes, Operation operations) { + public ClassDTO(String name_mclass, Attribute attributes, Operation operations) { this.name_mclass = name_mclass; this.attributes.add(attributes); this.operations.add(operations); } - public UseClass(String name_mclass) { + public ClassDTO(String name_mclass) { this.name_mclass = name_mclass; } - public UseClass() {} + public ClassDTO() {} } diff --git a/use-api/src/main/java/org/tzi/use/model/Invariant.java b/use-api/src/main/java/org/tzi/use/DTO/Invariant.java similarity index 96% rename from use-api/src/main/java/org/tzi/use/model/Invariant.java rename to use-api/src/main/java/org/tzi/use/DTO/Invariant.java index 2cdb722bf..3e8a8dbac 100644 --- a/use-api/src/main/java/org/tzi/use/model/Invariant.java +++ b/use-api/src/main/java/org/tzi/use/DTO/Invariant.java @@ -1,4 +1,4 @@ -package org.tzi.use.model; +package org.tzi.use.DTO; import jakarta.persistence.Id; diff --git a/use-api/src/main/java/org/tzi/use/model/Operation.java b/use-api/src/main/java/org/tzi/use/DTO/Operation.java similarity index 82% rename from use-api/src/main/java/org/tzi/use/model/Operation.java rename to use-api/src/main/java/org/tzi/use/DTO/Operation.java index de9da7b68..16f1589d0 100644 --- a/use-api/src/main/java/org/tzi/use/model/Operation.java +++ b/use-api/src/main/java/org/tzi/use/DTO/Operation.java @@ -1,4 +1,4 @@ -package org.tzi.use.model; +package org.tzi.use.DTO; import jakarta.persistence.Id; import org.springframework.data.mongodb.core.mapping.Document; @@ -12,7 +12,7 @@ public class Operation { // @ManyToOne // @JoinColumn(name = "name_mclass", nullable = false) -// private UseClass mclass; +// private ClassDTO mclass; // Getters and Setters @@ -33,11 +33,11 @@ public void setName(String name) { this.name = name; } -// public UseClass getMclass() { +// public ClassDTO getMclass() { // return mclass; // } // -// public void setMclass(UseClass mclass) { +// public void setMclass(ClassDTO mclass) { // this.mclass = mclass; // } @@ -46,7 +46,7 @@ public Operation(String name, String body) { this.name = name; this.body = body; } - public Operation(String name, UseClass mclass) { + public Operation(String name, ClassDTO mclass) { this.name = name; // this.mclass = mclass; } diff --git a/use-api/src/main/java/org/tzi/use/model/PrePostCondition.java b/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java similarity index 83% rename from use-api/src/main/java/org/tzi/use/model/PrePostCondition.java rename to use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java index a771c748a..ccdb9026c 100644 --- a/use-api/src/main/java/org/tzi/use/model/PrePostCondition.java +++ b/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java @@ -1,20 +1,20 @@ -package org.tzi.use.model; +package org.tzi.use.DTO; import jakarta.persistence.Id; import org.springframework.data.mongodb.core.mapping.Document; @Document -public class PrePostCondition { +public class PrePostConditionDTO { @Id private String operationName; private String name; private String condition; private boolean isPre; - public PrePostCondition() { + public PrePostConditionDTO() { } - public PrePostCondition(String operationName, String name, String condition, boolean isPre) { + public PrePostConditionDTO(String operationName, String name, String condition, boolean isPre) { this.operationName = operationName; this.name = name; this.condition = condition; diff --git a/use-api/src/main/java/org/tzi/use/MClassFacade.java b/use-api/src/main/java/org/tzi/use/MClassFacade.java index cac763d90..4cd4caf49 100644 --- a/use-api/src/main/java/org/tzi/use/MClassFacade.java +++ b/use-api/src/main/java/org/tzi/use/MClassFacade.java @@ -2,13 +2,13 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; -import org.tzi.use.model.*; +import org.tzi.use.DTO.*; import org.tzi.use.uml.mm.MClass; import org.tzi.use.uml.mm.MInvalidModelException; public class MClassFacade { - public static UseClass createMClass(UseClass aClass) throws UseApiException, MInvalidModelException { + public static ClassDTO createMClass(ClassDTO aClass) throws UseApiException, MInvalidModelException { UseModelApi useModelApi = new UseModelApi(); MClass mClass; mClass = useModelApi.createClass(aClass.getName_mclass(), false); @@ -21,8 +21,8 @@ public static UseClass createMClass(UseClass aClass) throws UseApiException, MIn useModelApi.createOperation(mClass.name(), operation.getName(), new String[0][0], operation.getBody()); } - for(PrePostCondition prePostCondition : aClass.getPrePostConditions()) { - useModelApi.createPrePostCondition(mClass.name(), prePostCondition.getOperationName(), prePostCondition.getName(), prePostCondition.getCondition(), prePostCondition.isPre()); + for(PrePostConditionDTO prePostConditionDTO : aClass.getPrePostConditions()) { + useModelApi.createPrePostCondition(mClass.name(), prePostConditionDTO.getOperationName(), prePostConditionDTO.getName(), prePostConditionDTO.getCondition(), prePostConditionDTO.isPre()); } for (Invariant invariant: aClass.getInvariants()) { diff --git a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java index c14b07f99..f86920355 100644 --- a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java +++ b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java @@ -1,13 +1,8 @@ package org.tzi.use; -import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.tzi.use.model.Attribute; -import org.tzi.use.model.UseClass; -import org.tzi.use.model.Operation; -import org.tzi.use.repository.ClassRepo; + //localhost 8080 not in use anymore @SpringBootApplication public class UseAPIApplication { @@ -21,7 +16,7 @@ public static void main(String[] args) { // Attribute name = new Attribute("name","String"); // Operation operation = new Operation("operation()"); // -// UseClass mclass2 = classRepo.save(new UseClass("TestClass2",name, operation)); +// ClassDTO mclass2 = classRepo.save(new ClassDTO("TestClass2",name, operation)); // // // }; diff --git a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java index 9e6b08c54..72974c0db 100644 --- a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java +++ b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java @@ -1,8 +1,7 @@ package org.tzi.use.repository; -import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.mongodb.repository.MongoRepository; -import org.tzi.use.model.UseClass; +import org.tzi.use.DTO.ClassDTO; -public interface ClassRepo extends MongoRepository { +public interface ClassRepo extends MongoRepository { } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java index 0d432bc74..3d7511692 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java @@ -5,7 +5,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.tzi.use.api.UseApiException; -import org.tzi.use.model.UseClass; +import org.tzi.use.DTO.ClassDTO; import org.tzi.use.rest.services.MClassRService; import org.tzi.use.uml.mm.MInvalidModelException; @@ -20,15 +20,15 @@ public class RestApiController { @GetMapping("/classes") - public ResponseEntity> getMClasses() { + public ResponseEntity> getMClasses() { return ResponseEntity.ok(mClassService.getAllMCLass()); } @PostMapping("/class") - public ResponseEntity createMClass(@RequestBody UseClass aUseClass) { + public ResponseEntity createMClass(@RequestBody ClassDTO aClassDTO) { try { - UseClass savedUseClass = mClassService.saveMClass(aUseClass); - return new ResponseEntity<>(savedUseClass, HttpStatus.CREATED); + ClassDTO savedClassDTO = mClassService.saveMClass(aClassDTO); + return new ResponseEntity<>(savedClassDTO, HttpStatus.CREATED); }catch (MInvalidModelException e) { // Return a detailed error message for MInvalidModelException return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java index dd75f8eae..05ca9bb96 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Service; import org.tzi.use.MClassFacade; import org.tzi.use.api.UseApiException; -import org.tzi.use.model.UseClass; +import org.tzi.use.DTO.ClassDTO; import org.tzi.use.repository.ClassRepo; import org.tzi.use.uml.mm.MInvalidModelException; @@ -16,16 +16,16 @@ public class MClassRService { @Autowired private ClassRepo classRepository; - public UseClass saveMClass(UseClass aUseClass) throws MInvalidModelException, UseApiException { - MClassFacade.createMClass(aUseClass); - if(classRepository.findById(aUseClass.getName_mclass()).isPresent()) { + public ClassDTO saveMClass(ClassDTO aClassDTO) throws MInvalidModelException, UseApiException { + MClassFacade.createMClass(aClassDTO); + if(classRepository.findById(aClassDTO.getName_mclass()).isPresent()) { // TODO Exception already exists throw new UseApiException("Class name already exists"); } - return classRepository.save(aUseClass); + return classRepository.save(aClassDTO); } - public List getAllMCLass(){ + public List getAllMCLass(){ return classRepository.findAll(); } } \ No newline at end of file diff --git a/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java b/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java index 01afd4708..eb936a268 100644 --- a/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java +++ b/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java @@ -18,7 +18,7 @@ public class RestApiControllerTest { // // @Test // public void testCreateMClass() { -// // Create a sample UseClass JSON payload +// // Create a sample ClassDTO JSON payload // String requestBody = "{\n" + // " \"name_mclass\": \"Class1\",\n" + // " \"attributes\": [\n" + @@ -52,7 +52,7 @@ public class RestApiControllerTest { // // @Test // public void testCreateDuplicateMClass() { -// // Create first UseClass with name "SameClass" +// // Create first ClassDTO with name "SameClass" // String requestBody = "{\n" + // " \"name_mclass\": \"SameClass\"\n" + // "}"; @@ -78,7 +78,7 @@ public class RestApiControllerTest { // // @Test // public void testCreateMClassWithoutName() { -// // Create UseClass with no name but with attributes and operations +// // Create ClassDTO with no name but with attributes and operations // String requestBody = "{\n" + // " \"attributes\": [\n" + // " {\n" + @@ -105,7 +105,7 @@ public class RestApiControllerTest { // // @Test // public void testCreateMClassWithEmptyPayload() { -// // Create UseClass with empty payload +// // Create ClassDTO with empty payload // String requestBody = "{}"; // // given() @@ -119,7 +119,7 @@ public class RestApiControllerTest { // // @Test // public void testCreateMClassWithInvalidJson() { -// // Create UseClass with invalid JSON structure +// // Create ClassDTO with invalid JSON structure // String requestBody = "{\n" + // " \"name_mclass\": \"Class1\",\n" + // " \"attributes\": [\n" + From e8a69ba8fe9dd8c3677f944bf18de91d140afa40 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 25 Sep 2025 22:50:26 +0200 Subject: [PATCH 045/148] DTO postfix added --- .../DTO/{Attribute.java => AttributeDTO.java} | 8 +-- .../main/java/org/tzi/use/DTO/ClassDTO.java | 54 +++++++++---------- .../DTO/{Invariant.java => InvariantDTO.java} | 6 +-- .../DTO/{Operation.java => OperationDTO.java} | 10 ++-- .../main/java/org/tzi/use/MClassFacade.java | 12 ++--- 5 files changed, 45 insertions(+), 45 deletions(-) rename use-api/src/main/java/org/tzi/use/DTO/{Attribute.java => AttributeDTO.java} (83%) rename use-api/src/main/java/org/tzi/use/DTO/{Invariant.java => InvariantDTO.java} (84%) rename use-api/src/main/java/org/tzi/use/DTO/{Operation.java => OperationDTO.java} (81%) diff --git a/use-api/src/main/java/org/tzi/use/DTO/Attribute.java b/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java similarity index 83% rename from use-api/src/main/java/org/tzi/use/DTO/Attribute.java rename to use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java index a6da6278a..d7c0186a9 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/Attribute.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java @@ -5,7 +5,7 @@ @Document - public class Attribute { + public class AttributeDTO { @Id private String name_attr; private String type; @@ -42,16 +42,16 @@ public void setType(String type) { // } //Constructors - public Attribute(String name_attr, String type){ + public AttributeDTO(String name_attr, String type){ this.name_attr = name_attr; this.type = type; } - public Attribute(String name, String string, ClassDTO mclass) { + public AttributeDTO(String name, String string, ClassDTO mclass) { this.name_attr = name; this.type = string; // this.mclass = mclass; } - public Attribute(){} + public AttributeDTO(){} } diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index ba0477752..01bf67b43 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -15,11 +15,11 @@ public class ClassDTO { // Unidirectional OneToMany relationship @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "mClass_id") - private List attributes = new ArrayList<>(); + private List attributeDTOS = new ArrayList<>(); // Unidirectional OneToMany relationship @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "mClass_id") - private List operations = new ArrayList<>(); + private List operationDTOS = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "mClass_id") @@ -27,43 +27,43 @@ public class ClassDTO { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "mClass_id") - private List invariants = new ArrayList<>(); + private List invariantDTOS = new ArrayList<>(); public String getName_mclass() { return name_mclass; } - public List getAttributes() { - return attributes; + public List getAttributes() { + return attributeDTOS; } - public List getOperations() { - return operations; + public List getOperations() { + return operationDTOS; } public List getPrePostConditions() { return prePostConditionDTOS; } - public List getInvariants() { - return invariants; + public List getInvariants() { + return invariantDTOS; } - public void addAttribute(Attribute attribute) { - attributes.add(attribute); + public void addAttribute(AttributeDTO attributeDTO) { + attributeDTOS.add(attributeDTO); } - public void removeAttribute(Attribute attribute) { - attributes.remove(attribute); + public void removeAttribute(AttributeDTO attributeDTO) { + attributeDTOS.remove(attributeDTO); } - public void addOperation(Operation operation) { - operations.add(operation); + public void addOperation(OperationDTO operationDTO) { + operationDTOS.add(operationDTO); } - public void removeOperation(Operation operation) { - operations.remove(operation); + public void removeOperation(OperationDTO operationDTO) { + operationDTOS.remove(operationDTO); } public void addPrePostCondition(PrePostConditionDTO condition) { @@ -74,26 +74,26 @@ public void removePrePostCondition(PrePostConditionDTO condition) { prePostConditionDTOS.remove(condition); } - public void addInvariant(Invariant invariant) { - invariants.add(invariant); + public void addInvariant(InvariantDTO invariantDTO) { + invariantDTOS.add(invariantDTO); } - public void removeInvariant(Invariant invariant) { - invariants.remove(invariant); + public void removeInvariant(InvariantDTO invariantDTO) { + invariantDTOS.remove(invariantDTO); } //Constructors - public ClassDTO(String name_mclass, List attributes, List operations) { + public ClassDTO(String name_mclass, List attributeDTOS, List operationDTOS) { this.name_mclass = name_mclass; - this.attributes = attributes; - this.operations = operations; + this.attributeDTOS = attributeDTOS; + this.operationDTOS = operationDTOS; } - public ClassDTO(String name_mclass, Attribute attributes, Operation operations) { + public ClassDTO(String name_mclass, AttributeDTO attributes, OperationDTO operations) { this.name_mclass = name_mclass; - this.attributes.add(attributes); - this.operations.add(operations); + this.attributeDTOS.add(attributes); + this.operationDTOS.add(operations); } public ClassDTO(String name_mclass) { this.name_mclass = name_mclass; diff --git a/use-api/src/main/java/org/tzi/use/DTO/Invariant.java b/use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java similarity index 84% rename from use-api/src/main/java/org/tzi/use/DTO/Invariant.java rename to use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java index 3e8a8dbac..238c4aae5 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/Invariant.java +++ b/use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java @@ -2,18 +2,18 @@ import jakarta.persistence.Id; -public class Invariant { +public class InvariantDTO { @Id private String invName; private String invBody; private boolean isExistential; - public Invariant() { + public InvariantDTO() { } - public Invariant(String invName, String invBody, boolean isExistential) { + public InvariantDTO(String invName, String invBody, boolean isExistential) { this.invName = invName; this.invBody = invBody; this.isExistential = isExistential; diff --git a/use-api/src/main/java/org/tzi/use/DTO/Operation.java b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java similarity index 81% rename from use-api/src/main/java/org/tzi/use/DTO/Operation.java rename to use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java index 16f1589d0..9644e19ee 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/Operation.java +++ b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java @@ -4,7 +4,7 @@ import org.springframework.data.mongodb.core.mapping.Document; @Document -public class Operation { +public class OperationDTO { @Id private String name; @@ -42,18 +42,18 @@ public void setName(String name) { // } //Constructors - public Operation(String name, String body) { + public OperationDTO(String name, String body) { this.name = name; this.body = body; } - public Operation(String name, ClassDTO mclass) { + public OperationDTO(String name, ClassDTO mclass) { this.name = name; // this.mclass = mclass; } - public Operation(String name) { + public OperationDTO(String name) { this.name = name; } - public Operation() {} + public OperationDTO() {} } diff --git a/use-api/src/main/java/org/tzi/use/MClassFacade.java b/use-api/src/main/java/org/tzi/use/MClassFacade.java index 4cd4caf49..f44a4dff5 100644 --- a/use-api/src/main/java/org/tzi/use/MClassFacade.java +++ b/use-api/src/main/java/org/tzi/use/MClassFacade.java @@ -12,21 +12,21 @@ public static ClassDTO createMClass(ClassDTO aClass) throws UseApiException, MIn UseModelApi useModelApi = new UseModelApi(); MClass mClass; mClass = useModelApi.createClass(aClass.getName_mclass(), false); - for (Attribute attribute : aClass.getAttributes()) { - useModelApi.createAttribute(mClass.name(), attribute.getName_attr(), attribute.getType()); + for (AttributeDTO attributeDTO : aClass.getAttributes()) { + useModelApi.createAttribute(mClass.name(), attributeDTO.getName_attr(), attributeDTO.getType()); } //parameter liste wird noch nicht unterstützt. -> daher new String [][] - for (Operation operation : aClass.getOperations()) { - useModelApi.createOperation(mClass.name(), operation.getName(), new String[0][0], operation.getBody()); + for (OperationDTO operationDTO : aClass.getOperations()) { + useModelApi.createOperation(mClass.name(), operationDTO.getName(), new String[0][0], operationDTO.getBody()); } for(PrePostConditionDTO prePostConditionDTO : aClass.getPrePostConditions()) { useModelApi.createPrePostCondition(mClass.name(), prePostConditionDTO.getOperationName(), prePostConditionDTO.getName(), prePostConditionDTO.getCondition(), prePostConditionDTO.isPre()); } - for (Invariant invariant: aClass.getInvariants()) { - useModelApi.createInvariant(mClass.name(), invariant.getInvName(), invariant.getInvBody(),invariant.isExistential()); + for (InvariantDTO invariantDTO : aClass.getInvariants()) { + useModelApi.createInvariant(mClass.name(), invariantDTO.getInvName(), invariantDTO.getInvBody(), invariantDTO.isExistential()); } return aClass; From 971506324846bf7fad03d437d0962c0d51012e40 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 25 Sep 2025 23:39:02 +0200 Subject: [PATCH 046/148] added more DTO's --- .../java/org/tzi/use/DTO/AssociationDTO.java | 162 ++++++++++++++++++ .../org/tzi/use/DTO/AssociationEndDTO.java | 4 + .../main/java/org/tzi/use/DTO/ModelDTO.java | 4 + 3 files changed, 170 insertions(+) create mode 100644 use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java create mode 100644 use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java create mode 100644 use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java new file mode 100644 index 000000000..fd575c135 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java @@ -0,0 +1,162 @@ +package org.tzi.use.DTO; + +import java.util.List; +import java.util.Set; + +public class AssociationDTO { + private String name; + private List associationEnds; + private List roleNames; + private Set associatedClassNames; + private Set subsets; + private Set subsettedBy; + private Set redefines; + private Set redefinedBy; + private boolean isUnion; + private boolean isReadOnly; + private boolean isOrdered; + private boolean isDerived; + private boolean isRedefining; + private boolean hasQualifiedEnds; + private int aggregationKind; + private int positionInModel; + + // Default constructor + public AssociationDTO() { + } + + // Constructor with essential fields + public AssociationDTO(String name, List associationEnds) { + this.name = name; + this.associationEnds = associationEnds; + } + + // Getters and setters + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getAssociationEnds() { + return associationEnds; + } + + public void setAssociationEnds(List associationEnds) { + this.associationEnds = associationEnds; + } + + public List getRoleNames() { + return roleNames; + } + + public void setRoleNames(List roleNames) { + this.roleNames = roleNames; + } + + public Set getAssociatedClassNames() { + return associatedClassNames; + } + + public void setAssociatedClassNames(Set associatedClassNames) { + this.associatedClassNames = associatedClassNames; + } + + public Set getSubsets() { + return subsets; + } + + public void setSubsets(Set subsets) { + this.subsets = subsets; + } + + public Set getSubsettedBy() { + return subsettedBy; + } + + public void setSubsettedBy(Set subsettedBy) { + this.subsettedBy = subsettedBy; + } + + public Set getRedefines() { + return redefines; + } + + public void setRedefines(Set redefines) { + this.redefines = redefines; + } + + public Set getRedefinedBy() { + return redefinedBy; + } + + public void setRedefinedBy(Set redefinedBy) { + this.redefinedBy = redefinedBy; + } + + public boolean isUnion() { + return isUnion; + } + + public void setUnion(boolean union) { + isUnion = union; + } + + public boolean isReadOnly() { + return isReadOnly; + } + + public void setReadOnly(boolean readOnly) { + isReadOnly = readOnly; + } + + public boolean isOrdered() { + return isOrdered; + } + + public void setOrdered(boolean ordered) { + isOrdered = ordered; + } + + public boolean isDerived() { + return isDerived; + } + + public void setDerived(boolean derived) { + isDerived = derived; + } + + public boolean isRedefining() { + return isRedefining; + } + + public void setRedefining(boolean redefining) { + isRedefining = redefining; + } + + public boolean isHasQualifiedEnds() { + return hasQualifiedEnds; + } + + public void setHasQualifiedEnds(boolean hasQualifiedEnds) { + this.hasQualifiedEnds = hasQualifiedEnds; + } + + public int getAggregationKind() { + return aggregationKind; + } + + public void setAggregationKind(int aggregationKind) { + this.aggregationKind = aggregationKind; + } + + public int getPositionInModel() { + return positionInModel; + } + + public void setPositionInModel(int positionInModel) { + this.positionInModel = positionInModel; + } +} diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java new file mode 100644 index 000000000..9b3bbc916 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java @@ -0,0 +1,4 @@ +package org.tzi.use.DTO; + +public class AssociationEndDTO { +} diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java new file mode 100644 index 000000000..2b2f2d27c --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -0,0 +1,4 @@ +package org.tzi.use.DTO; + +public class ModelDTO { +} From e7210c3d4afc438165709d143bbec104c314bf55 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 26 Sep 2025 01:35:50 +0200 Subject: [PATCH 047/148] added DTO code --- .../java/org/tzi/use/DTO/AssociationDTO.java | 166 ++---------------- .../main/java/org/tzi/use/DTO/ModelDTO.java | 20 +++ 2 files changed, 35 insertions(+), 151 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java index fd575c135..aabd12ab3 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java @@ -1,162 +1,26 @@ package org.tzi.use.DTO; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import jakarta.validation.Valid; import java.util.List; import java.util.Set; +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) public class AssociationDTO { private String name; + + @Valid private List associationEnds; + private List roleNames; private Set associatedClassNames; - private Set subsets; - private Set subsettedBy; - private Set redefines; - private Set redefinedBy; - private boolean isUnion; - private boolean isReadOnly; - private boolean isOrdered; - private boolean isDerived; - private boolean isRedefining; - private boolean hasQualifiedEnds; - private int aggregationKind; - private int positionInModel; - - // Default constructor - public AssociationDTO() { - } - - // Constructor with essential fields - public AssociationDTO(String name, List associationEnds) { - this.name = name; - this.associationEnds = associationEnds; - } - - // Getters and setters - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getAssociationEnds() { - return associationEnds; - } - - public void setAssociationEnds(List associationEnds) { - this.associationEnds = associationEnds; - } - - public List getRoleNames() { - return roleNames; - } - - public void setRoleNames(List roleNames) { - this.roleNames = roleNames; - } - - public Set getAssociatedClassNames() { - return associatedClassNames; - } - - public void setAssociatedClassNames(Set associatedClassNames) { - this.associatedClassNames = associatedClassNames; - } - - public Set getSubsets() { - return subsets; - } - - public void setSubsets(Set subsets) { - this.subsets = subsets; - } - - public Set getSubsettedBy() { - return subsettedBy; - } - - public void setSubsettedBy(Set subsettedBy) { - this.subsettedBy = subsettedBy; - } - - public Set getRedefines() { - return redefines; - } - - public void setRedefines(Set redefines) { - this.redefines = redefines; - } - - public Set getRedefinedBy() { - return redefinedBy; - } - - public void setRedefinedBy(Set redefinedBy) { - this.redefinedBy = redefinedBy; - } - - public boolean isUnion() { - return isUnion; - } - - public void setUnion(boolean union) { - isUnion = union; - } - - public boolean isReadOnly() { - return isReadOnly; - } - - public void setReadOnly(boolean readOnly) { - isReadOnly = readOnly; - } - - public boolean isOrdered() { - return isOrdered; - } - - public void setOrdered(boolean ordered) { - isOrdered = ordered; - } - - public boolean isDerived() { - return isDerived; - } - - public void setDerived(boolean derived) { - isDerived = derived; - } - - public boolean isRedefining() { - return isRedefining; - } - - public void setRedefining(boolean redefining) { - isRedefining = redefining; - } - - public boolean isHasQualifiedEnds() { - return hasQualifiedEnds; - } - - public void setHasQualifiedEnds(boolean hasQualifiedEnds) { - this.hasQualifiedEnds = hasQualifiedEnds; - } - - public int getAggregationKind() { - return aggregationKind; - } - - public void setAggregationKind(int aggregationKind) { - this.aggregationKind = aggregationKind; - } - - public int getPositionInModel() { - return positionInModel; - } - - public void setPositionInModel(int positionInModel) { - this.positionInModel = positionInModel; - } } diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index 2b2f2d27c..b5e763f99 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -1,4 +1,24 @@ package org.tzi.use.DTO; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@NoArgsConstructor public class ModelDTO { + private String name; + private String id; + private List classes = new ArrayList<>(); + private List associations = new ArrayList<>(); + private List invariants = new ArrayList<>(); + private List preConditions = new ArrayList<>(); + private List postConditions = new ArrayList<>(); + + public ModelDTO(String name, String id) { + this.name = name; + this.id = id; + } } From 2266d4c140b3ad41e8bcab65ac199a86ba0623e7 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 26 Sep 2025 01:36:13 +0200 Subject: [PATCH 048/148] model endpoint with hateoas --- use-api/pom.xml | 15 +++ ...{MClassFacade.java => UseModelFacade.java} | 8 +- .../org/tzi/use/repository/ModelRepo.java | 7 + .../use/rest/controller/ClassController.java | 8 ++ .../use/rest/controller/ModelController.java | 125 ++++++++++++++++++ .../tzi/use/rest/services/MClassRService.java | 4 +- .../tzi/use/rest/services/ModelService.java | 50 +++++++ 7 files changed, 213 insertions(+), 4 deletions(-) rename use-api/src/main/java/org/tzi/use/{MClassFacade.java => UseModelFacade.java} (87%) create mode 100644 use-api/src/main/java/org/tzi/use/repository/ModelRepo.java create mode 100644 use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java create mode 100644 use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java create mode 100644 use-api/src/main/java/org/tzi/use/rest/services/ModelService.java diff --git a/use-api/pom.xml b/use-api/pom.xml index e8979dc9a..ec459129c 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -46,6 +46,21 @@ org.springframework.boot spring-boot-starter-graphql + + org.projectlombok + lombok + 1.18.30 + provided + + + org.springframework.boot + spring-boot-starter-hateoas + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + org.springframework.boot spring-boot-starter-web diff --git a/use-api/src/main/java/org/tzi/use/MClassFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java similarity index 87% rename from use-api/src/main/java/org/tzi/use/MClassFacade.java rename to use-api/src/main/java/org/tzi/use/UseModelFacade.java index f44a4dff5..c6a3b3c5a 100644 --- a/use-api/src/main/java/org/tzi/use/MClassFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -6,10 +6,14 @@ import org.tzi.use.uml.mm.MClass; import org.tzi.use.uml.mm.MInvalidModelException; -public class MClassFacade { +public class UseModelFacade { + private static final UseModelApi useModelApi = new UseModelApi(); + + public static UseModelApi createModel(String modelName) { + return new UseModelApi(modelName); + } public static ClassDTO createMClass(ClassDTO aClass) throws UseApiException, MInvalidModelException { - UseModelApi useModelApi = new UseModelApi(); MClass mClass; mClass = useModelApi.createClass(aClass.getName_mclass(), false); for (AttributeDTO attributeDTO : aClass.getAttributes()) { diff --git a/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java b/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java new file mode 100644 index 000000000..51f6afeb0 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java @@ -0,0 +1,7 @@ +package org.tzi.use.repository; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.tzi.use.DTO.ModelDTO; + +public interface ModelRepo extends MongoRepository { +} diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java new file mode 100644 index 000000000..ce600ef2e --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -0,0 +1,8 @@ +package org.tzi.use.rest.controller; + +public class ClassController { + /* + Endpoint that are needed prefix /api/model/{id} + class should only have for attribute and operation (and assoc) + */ +} diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java new file mode 100644 index 000000000..e7663f9b3 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -0,0 +1,125 @@ +package org.tzi.use.rest.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; + +import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.api.UseApiException; +import org.tzi.use.rest.services.ModelService; + +@RestController +@RequestMapping("/api") +public class ModelController { + + @Autowired + private ModelService modelService; + + /** + * Create a new model + * @param modelDTO The model data to create + * @return The created model with HATEOAS links + */ + @PostMapping("/model") + public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { + try { + ModelDTO createdModel = modelService.createModel(modelDTO); + + // Create an EntityModel (HATEOAS) with the response + EntityModel entityModel = EntityModel.of(createdModel); + + // Add HATEOAS links + // Link to self + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelById(createdModel.getId())) + .withSelfRel()); + + // Link to get all classes in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(createdModel.getId())) + .withRel("classes")); + + // Link to get all associations in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(createdModel.getId())) + .withRel("associations")); + + // Link to get all invariants in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(createdModel.getId())) + .withRel("invariants")); + + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelPrePostConditions(createdModel.getId())) + .withRel("prepostconditions")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } catch (UseApiException e) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + /** + * Placeholder method to retrieve a model by ID + */ + @GetMapping("/model/{id}") + public ResponseEntity> getModelById(@PathVariable String id) { + // Implementation to be added + return null; + } + + /** + * Placeholder method to retrieve all classes in a model + */ + @GetMapping("/model/{id}/classes") + public ResponseEntity getModelClasses(@PathVariable String id) { + // Implementation to be added + return null; + } + + /** + * Placeholder method to retrieve all associations in a model + */ + @GetMapping("/model/{id}/associations") + public ResponseEntity getModelAssociations(@PathVariable String id) { + // Implementation to be added + return null; + } + + /** + * Placeholder method to retrieve all invariants in a model + */ + @GetMapping("/model/{id}/invariants") + public ResponseEntity getModelInvariants(@PathVariable String id) { + // Implementation to be added + return null; + } + + /** + * Placeholder method to retrieve all pre/post conditions in a model + */ + @GetMapping("/model/{id}/prepostconditions") + public ResponseEntity getModelPrePostConditions(@PathVariable String id) { + // Implementation to be added + return null; + } + + /* + Endpoints that are needed (prefix /api): + POST /model - Create a new model + POST /model/class - Add a new class to a model + GET /model/{id} - Retrieve a model by ID + GET /model/{id}/classes - Retrieve all classes in a model + GET /model/{id}/associations - Retrieve all association in a model + GET /model/{id}/invariants - Retrieve all invariants in a model + GET /model/{id}/prepostconditions - Retrieve all pre- / post-conditions in a model + */ +} diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java index 05ca9bb96..48f5d8ea1 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java @@ -2,7 +2,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.tzi.use.MClassFacade; +import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; import org.tzi.use.DTO.ClassDTO; import org.tzi.use.repository.ClassRepo; @@ -17,7 +17,7 @@ public class MClassRService { private ClassRepo classRepository; public ClassDTO saveMClass(ClassDTO aClassDTO) throws MInvalidModelException, UseApiException { - MClassFacade.createMClass(aClassDTO); + UseModelFacade.createMClass(aClassDTO); if(classRepository.findById(aClassDTO.getName_mclass()).isPresent()) { // TODO Exception already exists throw new UseApiException("Class name already exists"); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java new file mode 100644 index 000000000..5557712fb --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -0,0 +1,50 @@ +package org.tzi.use.rest.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.UseModelFacade; +import org.tzi.use.api.UseApiException; +import org.tzi.use.api.UseModelApi; +import org.tzi.use.repository.ModelRepo; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +@Service +public class ModelService { + @Autowired + private ModelRepo modelRepo; + + // In-memory storage for model API instances + private final Map modelInstances = new HashMap<>(); + + public ModelDTO createModel(ModelDTO modelDTO) throws UseApiException { + // Generate a unique ID for the model + String modelId = UUID.randomUUID().toString(); + + // Create a new model using the ModelFacade + UseModelApi modelApi = UseModelFacade.createModel(modelDTO.getName()); + + // Store the model instance for future use + modelInstances.put(modelId, modelApi); + + // Update the DTO with the ID + modelDTO.setId(modelId); + + // Save to repository + return modelRepo.save(modelDTO); + } + + + public ModelDTO getModelById(String id) throws UseApiException { + Optional modelDTO = modelRepo.findById(id); + if (modelDTO.isEmpty()) { + throw new UseApiException("Model not found with ID: " + id); + } + + return modelDTO.get(); + } +} From 1dbc6edb12768b6c4d8031bb67d3ccb51715d21a Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 26 Sep 2025 01:43:56 +0200 Subject: [PATCH 049/148] Model Get Endpoint added --- .../use/rest/controller/ModelController.java | 47 +++++++++++++++++-- .../tzi/use/rest/services/ModelService.java | 17 ++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index e7663f9b3..e8e8f39ae 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -68,12 +68,53 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m } /** - * Placeholder method to retrieve a model by ID + * Retrieve a model by its ID + * @param id The ID of the model to retrieve + * @return The model with HATEOAS links */ @GetMapping("/model/{id}") public ResponseEntity> getModelById(@PathVariable String id) { - // Implementation to be added - return null; + try { + ModelDTO model = modelService.getModelById(id); + + // Create an EntityModel (HATEOAS) with the response + EntityModel entityModel = EntityModel.of(model); + + // Add HATEOAS links + // Link to self + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelById(id)) + .withSelfRel()); + + // Link to get all classes in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(id)) + .withRel("classes")); + + // Link to get all associations in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(id)) + .withRel("associations")); + + // Link to get all invariants in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(id)) + .withRel("invariants")); + + // Link to get all pre/post conditions in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelPrePostConditions(id)) + .withRel("prepostconditions")); + + return new ResponseEntity<>(entityModel, HttpStatus.OK); + } catch (UseApiException e) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } } /** diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 5557712fb..404f54e2e 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -21,11 +21,18 @@ public class ModelService { // In-memory storage for model API instances private final Map modelInstances = new HashMap<>(); + /** + * Creates a new model with the given name + * + * @param modelDTO The DTO containing the model name and other properties + * @return The created model with assigned ID + * @throws UseApiException If there's an error creating the model + */ public ModelDTO createModel(ModelDTO modelDTO) throws UseApiException { // Generate a unique ID for the model String modelId = UUID.randomUUID().toString(); - // Create a new model using the ModelFacade + // Create a new model using the UseModelFacade UseModelApi modelApi = UseModelFacade.createModel(modelDTO.getName()); // Store the model instance for future use @@ -38,7 +45,13 @@ public ModelDTO createModel(ModelDTO modelDTO) throws UseApiException { return modelRepo.save(modelDTO); } - + /** + * Retrieves a model by its ID + * + * @param id The ID of the model to retrieve + * @return The model DTO + * @throws UseApiException If the model is not found + */ public ModelDTO getModelById(String id) throws UseApiException { Optional modelDTO = modelRepo.findById(id); if (modelDTO.isEmpty()) { From 536d1cc50430bdfcff0a2eac48851a9b70e57c1a Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 26 Sep 2025 02:34:24 +0200 Subject: [PATCH 050/148] dockerfile wrong also need mongodb so now docker compose --- use-api/Dockerfile | 20 -------------------- use-api/docker-compose.yml | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 20 deletions(-) delete mode 100644 use-api/Dockerfile create mode 100644 use-api/docker-compose.yml diff --git a/use-api/Dockerfile b/use-api/Dockerfile deleted file mode 100644 index e98fbf05f..000000000 --- a/use-api/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM maven:3.8-eclipse-temurin-17 AS builder - -WORKDIR /app - -COPY pom.xml . - -COPY src ./src - -RUN mvn package -DskipTests - - -FROM eclipse-temurin:17-jre-alpine - -WORKDIR /app - -COPY --from=builder /app/target/*.jar app.jar - -EXPOSE 8080 - -ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml new file mode 100644 index 000000000..1c7a973ba --- /dev/null +++ b/use-api/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.8' + +services: + mongodb: + image: mongo:latest + container_name: mongodb_cicd + ports: + - "27017:27017" + volumes: + - mongodb_data:/data/db + environment: + - MONGO_INITDB_ROOT_USERNAME=rootuser + - MONGO_INITDB_ROOT_PASSWORD=rootpass + - MONGO_INITDB_DATABASE=use-database + + use-api: + build: . + container_name: use-api + ports: + - "8080:8080" + depends_on: + - mongodb + environment: + - SPRING_DATA_MONGODB_HOST=mongodb_cicd + +volumes: + mongodb_data: \ No newline at end of file From 0012d924f241b10a14406a7dd5767fcbc0d8a17e Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 26 Sep 2025 08:47:01 +0200 Subject: [PATCH 051/148] simple dockerfile to start the use_web_api --- use-api/Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 use-api/Dockerfile diff --git a/use-api/Dockerfile b/use-api/Dockerfile new file mode 100644 index 000000000..7f81784de --- /dev/null +++ b/use-api/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:21-jdk-slim + +WORKDIR /app + +COPY target/use-api-*.jar app.jar + +EXPOSE 8080 + +ENTRYPOINT ["java","-jar","app.jar"] \ No newline at end of file From 601dcf8542a7de8eea1d784004012ef3cd1de5d3 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 26 Sep 2025 09:12:39 +0200 Subject: [PATCH 052/148] Enhance CI workflow with Postman and Docker uploads Added steps to upload Postman tests and Docker image, and modified artifact download steps. Now will do a better system test with the postman test against the deployable docker image. --- .github/workflows/maven.yml | 72 ++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ec87b62f1..2e8ac9614 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -43,58 +43,64 @@ jobs: with: name: constructed_use-api path: testphase - + + - name: Upload postman tests + run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests + - uses: actions/upload-artifact@v4 + with: + name: postman_tests + path: postmantests + + - name: Upload docker image + run: mkdir docker && cp use-api/docker-compose.yml docker && cp use-api/Dockerfile docker + - uses: actions/upload-artifact@v4 + with: + name: docker_image + path: docker + + test: needs: build runs-on: ubuntu-latest - services: - mongo: - image: mongo:4.4 - ports: - - 27017:27017 - steps: - #Checkout repository - - name: Checkout code - uses: actions/checkout@v3 # dont need to checkout if I put the postman collection into the artifact - - # Set up JDK - name: Set up Java uses: actions/setup-java@v3 with: java-version: '21' distribution: 'adopt' - #cache: maven - - name: Download Artifact use-api + + - name: Download Artifact use-api jar uses: actions/download-artifact@v4 with: name: constructed_use-api - + + - name: Download Artifact postman tests + uses: actions/download-artifact@v4 + with: + name: postman_tests + + - name: Download Aritfact Dockerimage + uses: actions/download-artifact@v4 + with: + name: docker_image - - # Start Spring Boot - - name: Start Spring Boot - run: java -Dspring.profiles.active=test -jar use-api-7.1.1.jar & - env: - SPRING_DATA_MONGODB_URI: mongodb://localhost:27017/testdb + - name: move the jar + run: mkdir target && cp use-api-7.1.1.jar target - # Wait for Spring Boot to start - - name: Wait for Spring Boot - run: | - for i in {1..5}; do - curl --fail http://localhost:8080/actuator/health && break || sleep 10; - done + - name: Run docker compose + run: docker-compose up -d + + - name: Wait for docker to be ready + run: sleep 20 - # Run Postman Tests with Newman - name: Run Postman tests run: | npm install -g newman - newman run use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json - + newman run use-webapi.postman_collection.json - # Cleanup - - name: Stop Spring Boot - run: pkill -f 'java -Dspring.profiles.active=test' + - name: Stop services + if: always() + run: docker-compose down From 550a96c7092b4437fad5fa186c1c2e3665d1f5a9 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Fri, 26 Sep 2025 09:22:32 +0200 Subject: [PATCH 053/148] Small mistake "-" --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2e8ac9614..102bcaf2c 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -91,7 +91,7 @@ jobs: run: mkdir target && cp use-api-7.1.1.jar target - name: Run docker compose - run: docker-compose up -d + run: docker compose up -d - name: Wait for docker to be ready run: sleep 20 From 941a71450ae9a38b78a1f4d2d6a8a18deaffa26e Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 29 Sep 2025 17:44:39 +0200 Subject: [PATCH 054/148] small change... localhost:8080/docs for swagger ui --- use-api/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index 4a37a9cfe..6c231f1ef 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -7,7 +7,7 @@ spring.main.allow-bean-definition-overriding=true server.port=8080 # /api-docs endpoint custom path -springdoc.api-docs.path=/docs +springdoc.swagger-ui.path=/docs springdoc.swagger-ui.operationsSorter=method springdoc.swagger-ui.filter=true From 27098e4a98c615c9b2710336d02a13328da6c286 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 29 Sep 2025 17:53:58 +0200 Subject: [PATCH 055/148] few deprecated --- use-api/src/main/java/org/tzi/use/UseModelFacade.java | 1 + .../main/java/org/tzi/use/rest/controller/RestApiController.java | 1 + 2 files changed, 2 insertions(+) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index c6a3b3c5a..eae7da2b2 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -13,6 +13,7 @@ public static UseModelApi createModel(String modelName) { return new UseModelApi(modelName); } + @Deprecated public static ClassDTO createMClass(ClassDTO aClass) throws UseApiException, MInvalidModelException { MClass mClass; mClass = useModelApi.createClass(aClass.getName_mclass(), false); diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java index 3d7511692..362da0816 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java @@ -11,6 +11,7 @@ import java.util.List; +@Deprecated @RestController //@RequestMapping("/api") guidelines public class RestApiController { From 3f75e480426a51282b3d1df0ee2841c6320f8fcc Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 29 Sep 2025 18:28:24 +0200 Subject: [PATCH 056/148] get all models endpoint --- .../use/rest/controller/ModelController.java | 70 +++++++++++++++++++ .../tzi/use/rest/services/ModelService.java | 10 +++ 2 files changed, 80 insertions(+) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index e8e8f39ae..eae674429 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -5,12 +5,16 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.tzi.use.DTO.ModelDTO; import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ModelService; +import java.util.List; +import java.util.stream.Collectors; + @RestController @RequestMapping("/api") public class ModelController { @@ -117,6 +121,72 @@ public ResponseEntity> getModelById(@PathVariable String i } } + /** + * Retrieve all models + * @return List of all models with HATEOAS links + */ + @GetMapping("/models") + public ResponseEntity>> getAllModels() { + List models = modelService.getAllModels(); + + // Convert each model to an EntityModel with links + List> modelEntities = models.stream() + .map(model -> { + EntityModel entityModel = EntityModel.of(model); + + // Add self link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelById(model.getId())) + .withSelfRel()); + + // Add classes link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(model.getId())) + .withRel("classes")); + + // Add associations link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(model.getId())) + .withRel("associations")); + + // Add invariants link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(model.getId())) + .withRel("invariants")); + + // Add pre/post conditions link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelPrePostConditions(model.getId())) + .withRel("prepostconditions")); + + return entityModel; + }) + .collect(Collectors.toList()); + + // Create a CollectionModel (container of EntityModels) + CollectionModel> collectionModel = + CollectionModel.of(modelEntities); + + // Add link to this collection + collectionModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getAllModels()) + .withSelfRel()); + + // Add link to create a new model + collectionModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .createModel(null)) + .withRel("create-model")); + + return new ResponseEntity<>(collectionModel, HttpStatus.OK); + } + /** * Placeholder method to retrieve all classes in a model */ diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 404f54e2e..a71c720b0 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -9,6 +9,7 @@ import org.tzi.use.repository.ModelRepo; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -60,4 +61,13 @@ public ModelDTO getModelById(String id) throws UseApiException { return modelDTO.get(); } + + /** + * Retrieves all available models + * + * @return List of all model DTOs + */ + public List getAllModels() { + return modelRepo.findAll(); + } } From 9d30a4a1e585a8bb5ef70055516d852992207bd4 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 29 Sep 2025 18:28:39 +0200 Subject: [PATCH 057/148] more depr --- .../main/java/org/tzi/use/UseModelFacade.java | 40 +++++++++---------- .../tzi/use/rest/services/MClassRService.java | 9 +++-- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index eae7da2b2..cc0dc96b3 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -15,25 +15,25 @@ public static UseModelApi createModel(String modelName) { @Deprecated public static ClassDTO createMClass(ClassDTO aClass) throws UseApiException, MInvalidModelException { - MClass mClass; - mClass = useModelApi.createClass(aClass.getName_mclass(), false); - for (AttributeDTO attributeDTO : aClass.getAttributes()) { - useModelApi.createAttribute(mClass.name(), attributeDTO.getName_attr(), attributeDTO.getType()); - - } - //parameter liste wird noch nicht unterstützt. -> daher new String [][] - for (OperationDTO operationDTO : aClass.getOperations()) { - useModelApi.createOperation(mClass.name(), operationDTO.getName(), new String[0][0], operationDTO.getBody()); - } - - for(PrePostConditionDTO prePostConditionDTO : aClass.getPrePostConditions()) { - useModelApi.createPrePostCondition(mClass.name(), prePostConditionDTO.getOperationName(), prePostConditionDTO.getName(), prePostConditionDTO.getCondition(), prePostConditionDTO.isPre()); - } - - for (InvariantDTO invariantDTO : aClass.getInvariants()) { - useModelApi.createInvariant(mClass.name(), invariantDTO.getInvName(), invariantDTO.getInvBody(), invariantDTO.isExistential()); - } - - return aClass; +// MClass mClass; +// mClass = useModelApi.createClass(aClass.getName_mclass(), false); +// for (AttributeDTO attributeDTO : aClass.getAttributes()) { +// useModelApi.createAttribute(mClass.name(), attributeDTO.getName_attr(), attributeDTO.getType()); +// +// } +// //parameter liste wird noch nicht unterstützt. -> daher new String [][] +// for (OperationDTO operationDTO : aClass.getOperations()) { +// useModelApi.createOperation(mClass.name(), operationDTO.getName(), new String[0][0], operationDTO.getBody()); +// } +// +// for(PrePostConditionDTO prePostConditionDTO : aClass.getPrePostConditions()) { +// useModelApi.createPrePostCondition(mClass.name(), prePostConditionDTO.getOperationName(), prePostConditionDTO.getName(), prePostConditionDTO.getCondition(), prePostConditionDTO.isPre()); +// } +// +// for (InvariantDTO invariantDTO : aClass.getInvariants()) { +// useModelApi.createInvariant(mClass.name(), invariantDTO.getInvName(), invariantDTO.getInvBody(), invariantDTO.isExistential()); +// } +// + return null; } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java index 48f5d8ea1..1fc0e6744 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java @@ -16,12 +16,13 @@ public class MClassRService { @Autowired private ClassRepo classRepository; + @Deprecated public ClassDTO saveMClass(ClassDTO aClassDTO) throws MInvalidModelException, UseApiException { UseModelFacade.createMClass(aClassDTO); - if(classRepository.findById(aClassDTO.getName_mclass()).isPresent()) { - // TODO Exception already exists - throw new UseApiException("Class name already exists"); - } +// if(classRepository.findById(aClassDTO.getName_mclass()).isPresent()) { +// // TODO Exception already exists +// throw new UseApiException("Class name already exists"); +// } return classRepository.save(aClassDTO); } From a987c85b78a5dd78a192d8da09d88503780f1fed Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 29 Sep 2025 18:28:51 +0200 Subject: [PATCH 058/148] lombok and correct annotations --- .../java/org/tzi/use/DTO/AttributeDTO.java | 67 ++++--------- .../main/java/org/tzi/use/DTO/ClassDTO.java | 99 ++++++------------- .../java/org/tzi/use/DTO/OperationDTO.java | 54 +++------- 3 files changed, 67 insertions(+), 153 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java index d7c0186a9..cb6e9c599 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java @@ -1,57 +1,32 @@ package org.tzi.use.DTO; -import jakarta.persistence.*; +import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; - +import lombok.Data; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; @Document - public class AttributeDTO { - @Id - private String name_attr; - private String type; - -// @ManyToOne -// @JoinColumn(name = "name_mclass", nullable = false) -// private ClassDTO mclass; - - - // Getters and Setters - - public String getName_attr() { - return name_attr; - } - - public void setName_attr(String name_attr) { - this.name_attr = name_attr; - } - - public String getType() { - return type; - } - - public void setType(String type) { +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AttributeDTO { + @Id + private String id; + private String name; + private String type; + + // Constructors for backward compatibility + public AttributeDTO(String name, String type){ + this.name = name; this.type = type; } -// public ClassDTO getMclass() { -// return mclass; -// } -// -// public void setMclass(ClassDTO mclass) { -// this.mclass = mclass; -// } - - //Constructors - public AttributeDTO(String name_attr, String type){ - this.name_attr = name_attr; + public AttributeDTO(String id, String name, String type, ClassDTO mclass) { + this.id = id; + this.name = name; this.type = type; } - - public AttributeDTO(String name, String string, ClassDTO mclass) { - this.name_attr = name; - this.type = string; -// this.mclass = mclass; - } - - public AttributeDTO(){} } diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index 01bf67b43..2c1f7563a 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -1,54 +1,34 @@ package org.tzi.use.DTO; -import jakarta.persistence.*; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.DBRef; +import lombok.Data; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; import java.util.ArrayList; import java.util.List; @Document +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder public class ClassDTO { @Id - private String name_mclass; - // Unidirectional OneToMany relationship - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "mClass_id") - private List attributeDTOS = new ArrayList<>(); - // Unidirectional OneToMany relationship - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "mClass_id") - private List operationDTOS = new ArrayList<>(); - - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "mClass_id") - private List prePostConditionDTOS = new ArrayList<>(); - - @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "mClass_id") - private List invariantDTOS = new ArrayList<>(); - - public String getName_mclass() { - return name_mclass; - } - + private String id; + private String name; - public List getAttributes() { - return attributeDTOS; - } - - public List getOperations() { - return operationDTOS; - } - - public List getPrePostConditions() { - return prePostConditionDTOS; - } + @DBRef + @Builder.Default + private List attributeDTOS = new ArrayList<>(); - public List getInvariants() { - return invariantDTOS; - } + @DBRef + @Builder.Default + private List operationDTOS = new ArrayList<>(); public void addAttribute(AttributeDTO attributeDTO) { attributeDTOS.add(attributeDTO); @@ -66,38 +46,21 @@ public void removeOperation(OperationDTO operationDTO) { operationDTOS.remove(operationDTO); } - public void addPrePostCondition(PrePostConditionDTO condition) { - prePostConditionDTOS.add(condition); - } - - public void removePrePostCondition(PrePostConditionDTO condition) { - prePostConditionDTOS.remove(condition); + // Additional constructor + public ClassDTO(String id, String name, AttributeDTO attributes, OperationDTO operations) { + this.id = id; + this.name = name; + this.attributeDTOS = new ArrayList<>(); + this.operationDTOS = new ArrayList<>(); + if (attributes != null) this.attributeDTOS.add(attributes); + if (operations != null) this.operationDTOS.add(operations); } - public void addInvariant(InvariantDTO invariantDTO) { - invariantDTOS.add(invariantDTO); + // Convenience constructor + public ClassDTO(String id, String name) { + this.id = id; + this.name = name; + this.attributeDTOS = new ArrayList<>(); + this.operationDTOS = new ArrayList<>(); } - - public void removeInvariant(InvariantDTO invariantDTO) { - invariantDTOS.remove(invariantDTO); - } - - - - //Constructors - public ClassDTO(String name_mclass, List attributeDTOS, List operationDTOS) { - this.name_mclass = name_mclass; - this.attributeDTOS = attributeDTOS; - this.operationDTOS = operationDTOS; - } - public ClassDTO(String name_mclass, AttributeDTO attributes, OperationDTO operations) { - this.name_mclass = name_mclass; - this.attributeDTOS.add(attributes); - this.operationDTOS.add(operations); - } - public ClassDTO(String name_mclass) { - this.name_mclass = name_mclass; - } - public ClassDTO() {} - } diff --git a/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java index 9644e19ee..4aebec1ed 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java @@ -1,59 +1,35 @@ package org.tzi.use.DTO; -import jakarta.persistence.Id; +import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import lombok.Data; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; @Document +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder public class OperationDTO { @Id + private String id; private String name; - private String body; -// @ManyToOne -// @JoinColumn(name = "name_mclass", nullable = false) -// private ClassDTO mclass; - - - // Getters and Setters - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -// public ClassDTO getMclass() { -// return mclass; -// } -// -// public void setMclass(ClassDTO mclass) { -// this.mclass = mclass; -// } - - //Constructors + // Constructors for backward compatibility public OperationDTO(String name, String body) { this.name = name; this.body = body; } - public OperationDTO(String name, ClassDTO mclass) { + + public OperationDTO(String id, String name, ClassDTO mclass) { + this.id = id; this.name = name; -// this.mclass = mclass; } + public OperationDTO(String name) { this.name = name; } - public OperationDTO() {} - - } From 811f091c8ea28310a34cbfad6d31e3da7c30fcc0 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 2 Oct 2025 23:01:18 +0200 Subject: [PATCH 059/148] added mapstruct --- use-api/pom.xml | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/use-api/pom.xml b/use-api/pom.xml index ec459129c..e214e5597 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -56,6 +56,11 @@ org.springframework.boot spring-boot-starter-hateoas + + org.mapstruct + mapstruct + 1.6.3 + jakarta.persistence jakarta.persistence-api @@ -145,27 +150,6 @@ - - - - - - - - - - - - - - - - - - - - - From 97ec576b5cdd64ee8205387c3c0590046b7d3ce9 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 2 Oct 2025 23:01:38 +0200 Subject: [PATCH 060/148] depreacted --- use-api/src/main/java/org/tzi/use/Mapper.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 use-api/src/main/java/org/tzi/use/Mapper.java diff --git a/use-api/src/main/java/org/tzi/use/Mapper.java b/use-api/src/main/java/org/tzi/use/Mapper.java new file mode 100644 index 000000000..4a3db50cf --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/Mapper.java @@ -0,0 +1,10 @@ +package org.tzi.use; + +@Deprecated +final public class Mapper { + private Mapper() { + throw new IllegalStateException("Utility class"); + } + + +} From 2a1949387a766757dd80ac8179e85ae19a9cfc64 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 2 Oct 2025 23:41:23 +0200 Subject: [PATCH 061/148] pomxml addition --- use-api/pom.xml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/use-api/pom.xml b/use-api/pom.xml index e214e5597..b54f4ccc7 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -61,6 +61,11 @@ mapstruct 1.6.3 + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + jakarta.persistence jakarta.persistence-api @@ -150,6 +155,35 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + + + org.mapstruct + mapstruct-processor + 1.6.3 + + + org.projectlombok + lombok + 1.18.30 + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + + + + + -Amapstruct.defaultComponentModel=spring + + + + From edf3855c0f55d43f098eee2ee6993a8ad2a8ef5f Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 2 Oct 2025 23:42:05 +0200 Subject: [PATCH 062/148] Refactor model persistence to use ModelNTT entity Introduced ModelNTT entity for MongoDB storage and updated repository, service, and controller logic to use ModelNTT instead of ModelDTO. Added ModelMapper for DTO-entity conversion via MapStruct. Removed unused fields and methods related to model ID and pre/post conditions, and updated endpoints to reference model name as the identifier. --- .../main/java/org/tzi/use/DTO/ModelDTO.java | 15 +++-- .../java/org/tzi/use/entities/ModelNTT.java | 29 +++++++++ .../java/org/tzi/use/mapper/ModelMapper.java | 18 ++++++ .../org/tzi/use/repository/ModelRepo.java | 4 +- .../use/rest/controller/ModelController.java | 64 ++++++++++--------- .../tzi/use/rest/services/ModelService.java | 45 ++++++------- 6 files changed, 108 insertions(+), 67 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/entities/ModelNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/mapper/ModelMapper.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index b5e763f99..872afd5a9 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -1,24 +1,25 @@ package org.tzi.use.DTO; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import java.util.ArrayList; import java.util.List; @Data +@AllArgsConstructor +//@RequiredArgsConstructor @NoArgsConstructor public class ModelDTO { private String name; - private String id; +// private String id; private List classes = new ArrayList<>(); private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); - private List preConditions = new ArrayList<>(); - private List postConditions = new ArrayList<>(); +// private List preConditions = new ArrayList<>(); +// private List postConditions = new ArrayList<>(); - public ModelDTO(String name, String id) { + public ModelDTO(String name) { this.name = name; - this.id = id; } + } diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java new file mode 100644 index 000000000..4ed25afc7 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -0,0 +1,29 @@ +package org.tzi.use.entities; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.tzi.use.DTO.ClassDTO; + +import java.util.ArrayList; +import java.util.List; + +@Document("model") +@Data +@AllArgsConstructor +@NoArgsConstructor +//@RequiredArgsConstructor +public class ModelNTT { + @Id + private String name; + private List classes = new ArrayList<>(); + private List associations = new ArrayList<>(); + private List invariants = new ArrayList<>(); + + public ModelNTT(String name) { + this.name = name; + } +} diff --git a/use-api/src/main/java/org/tzi/use/mapper/ModelMapper.java b/use-api/src/main/java/org/tzi/use/mapper/ModelMapper.java new file mode 100644 index 000000000..ae90f231a --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/ModelMapper.java @@ -0,0 +1,18 @@ +package org.tzi.use.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.entities.ModelNTT; + +/** + * MapStruct mapper to convert between ModelNTT (entity) and ModelDTO (data transfer object). + * Implementation will be generated by MapStruct at compile time and registered as a Spring bean. + */ +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface ModelMapper { + + ModelDTO toDTO(ModelNTT entity); + + ModelNTT toEntity(ModelDTO dto); +} diff --git a/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java b/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java index 51f6afeb0..9378d247e 100644 --- a/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java +++ b/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java @@ -1,7 +1,7 @@ package org.tzi.use.repository; import org.springframework.data.mongodb.repository.MongoRepository; -import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.entities.ModelNTT; -public interface ModelRepo extends MongoRepository { +public interface ModelRepo extends MongoRepository { } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index eae674429..72553b966 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -30,7 +30,9 @@ public class ModelController { @PostMapping("/model") public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { try { + System.out.println("bin ich hier drinne?"); ModelDTO createdModel = modelService.createModel(modelDTO); + System.out.println("und hier?"); // Create an EntityModel (HATEOAS) with the response EntityModel entityModel = EntityModel.of(createdModel); @@ -39,31 +41,31 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m // Link to self entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(createdModel.getId())) + .getModelById(createdModel.getName())) .withSelfRel()); // Link to get all classes in this model entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(createdModel.getId())) + .getModelClasses(createdModel.getName())) .withRel("classes")); // Link to get all associations in this model entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(createdModel.getId())) + .getModelAssociations(createdModel.getName())) .withRel("associations")); // Link to get all invariants in this model entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(createdModel.getId())) + .getModelInvariants(createdModel.getName())) .withRel("invariants")); - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelPrePostConditions(createdModel.getId())) - .withRel("prepostconditions")); +// entityModel.add(WebMvcLinkBuilder.linkTo( +// WebMvcLinkBuilder.methodOn(ModelController.class) +// .getModelPrePostConditions(createdModel.getId())) +// .withRel("prepostconditions")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } catch (UseApiException e) { @@ -79,7 +81,7 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m @GetMapping("/model/{id}") public ResponseEntity> getModelById(@PathVariable String id) { try { - ModelDTO model = modelService.getModelById(id); + ModelDTO model = modelService.getModelByName(id); // Create an EntityModel (HATEOAS) with the response EntityModel entityModel = EntityModel.of(model); @@ -109,11 +111,11 @@ public ResponseEntity> getModelById(@PathVariable String i .getModelInvariants(id)) .withRel("invariants")); - // Link to get all pre/post conditions in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelPrePostConditions(id)) - .withRel("prepostconditions")); +// // Link to get all pre/post conditions in this model +// entityModel.add(WebMvcLinkBuilder.linkTo( +// WebMvcLinkBuilder.methodOn(ModelController.class) +// .getModelPrePostConditions(id)) +// .withRel("prepostconditions")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } catch (UseApiException e) { @@ -137,32 +139,32 @@ public ResponseEntity>> getAllModels() { // Add self link entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(model.getId())) + .getModelById(model.getName())) .withSelfRel()); // Add classes link entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(model.getId())) + .getModelClasses(model.getName())) .withRel("classes")); // Add associations link entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(model.getId())) + .getModelAssociations(model.getName())) .withRel("associations")); // Add invariants link entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(model.getId())) + .getModelInvariants(model.getName())) .withRel("invariants")); - // Add pre/post conditions link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelPrePostConditions(model.getId())) - .withRel("prepostconditions")); +// // Add pre/post conditions link +// entityModel.add(WebMvcLinkBuilder.linkTo( +// WebMvcLinkBuilder.methodOn(ModelController.class) +// .getModelPrePostConditions(model.getId())) +// .withRel("prepostconditions")); return entityModel; }) @@ -214,14 +216,14 @@ public ResponseEntity getModelInvariants(@PathVariable String id) { return null; } - /** - * Placeholder method to retrieve all pre/post conditions in a model - */ - @GetMapping("/model/{id}/prepostconditions") - public ResponseEntity getModelPrePostConditions(@PathVariable String id) { - // Implementation to be added - return null; - } +// /** +// * Placeholder method to retrieve all pre/post conditions in a model +// */ +// @GetMapping("/model/{id}/prepostconditions") +// public ResponseEntity getModelPrePostConditions(@PathVariable String id) { +// // Implementation to be added +// return null; +// } /* Endpoints that are needed (prefix /api): diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index a71c720b0..ec0ff06c9 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -6,44 +6,35 @@ import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; +import org.tzi.use.entities.ModelNTT; +import org.tzi.use.mapper.ModelMapper; import org.tzi.use.repository.ModelRepo; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.UUID; @Service public class ModelService { @Autowired private ModelRepo modelRepo; + @Autowired + private ModelMapper modelMapper; - // In-memory storage for model API instances - private final Map modelInstances = new HashMap<>(); /** * Creates a new model with the given name * - * @param modelDTO The DTO containing the model name and other properties + * @param modelDTOreq The DTO containing the model name and other properties * @return The created model with assigned ID * @throws UseApiException If there's an error creating the model */ - public ModelDTO createModel(ModelDTO modelDTO) throws UseApiException { - // Generate a unique ID for the model - String modelId = UUID.randomUUID().toString(); - - // Create a new model using the UseModelFacade - UseModelApi modelApi = UseModelFacade.createModel(modelDTO.getName()); - - // Store the model instance for future use - modelInstances.put(modelId, modelApi); - - // Update the DTO with the ID - modelDTO.setId(modelId); + public ModelDTO createModel(ModelDTO modelDTOreq) throws UseApiException { + ModelNTT tmp_modelntt = modelMapper.toEntity(modelDTOreq); + UseModelApi modelApi = UseModelFacade.createModel(tmp_modelntt.getName()); // Save to repository - return modelRepo.save(modelDTO); + modelRepo.save(tmp_modelntt); + return modelMapper.toDTO(tmp_modelntt); } /** @@ -53,13 +44,10 @@ public ModelDTO createModel(ModelDTO modelDTO) throws UseApiException { * @return The model DTO * @throws UseApiException If the model is not found */ - public ModelDTO getModelById(String id) throws UseApiException { - Optional modelDTO = modelRepo.findById(id); - if (modelDTO.isEmpty()) { - throw new UseApiException("Model not found with ID: " + id); - } - - return modelDTO.get(); + public ModelDTO getModelByName(String name) throws UseApiException { + Optional tmp_modelntt = modelRepo.findById(name); + ModelDTO tmp_modeldto = modelMapper.toDTO(tmp_modelntt.get()); + return tmp_modeldto; } /** @@ -68,6 +56,9 @@ public ModelDTO getModelById(String id) throws UseApiException { * @return List of all model DTOs */ public List getAllModels() { - return modelRepo.findAll(); + return modelRepo.findAll() + .stream() + .map(modelMapper::toDTO) + .toList(); } } From c05ef7beff48fe9cdec9c55ce1acee7bfd0841ae Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 3 Oct 2025 20:08:16 +0200 Subject: [PATCH 063/148] clean up --- use-api/src/main/java/org/tzi/use/Mapper.java | 10 ----- .../use/rest/controller/ModelController.java | 25 +---------- .../rest/controller/RestApiController.java | 44 ------------------- 3 files changed, 1 insertion(+), 78 deletions(-) delete mode 100644 use-api/src/main/java/org/tzi/use/Mapper.java delete mode 100644 use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java diff --git a/use-api/src/main/java/org/tzi/use/Mapper.java b/use-api/src/main/java/org/tzi/use/Mapper.java deleted file mode 100644 index 4a3db50cf..000000000 --- a/use-api/src/main/java/org/tzi/use/Mapper.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.tzi.use; - -@Deprecated -final public class Mapper { - private Mapper() { - throw new IllegalStateException("Utility class"); - } - - -} diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 72553b966..979585c65 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -62,10 +62,6 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m .getModelInvariants(createdModel.getName())) .withRel("invariants")); -// entityModel.add(WebMvcLinkBuilder.linkTo( -// WebMvcLinkBuilder.methodOn(ModelController.class) -// .getModelPrePostConditions(createdModel.getId())) -// .withRel("prepostconditions")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } catch (UseApiException e) { @@ -111,11 +107,6 @@ public ResponseEntity> getModelById(@PathVariable String i .getModelInvariants(id)) .withRel("invariants")); -// // Link to get all pre/post conditions in this model -// entityModel.add(WebMvcLinkBuilder.linkTo( -// WebMvcLinkBuilder.methodOn(ModelController.class) -// .getModelPrePostConditions(id)) -// .withRel("prepostconditions")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } catch (UseApiException e) { @@ -160,11 +151,6 @@ public ResponseEntity>> getAllModels() { .getModelInvariants(model.getName())) .withRel("invariants")); -// // Add pre/post conditions link -// entityModel.add(WebMvcLinkBuilder.linkTo( -// WebMvcLinkBuilder.methodOn(ModelController.class) -// .getModelPrePostConditions(model.getId())) -// .withRel("prepostconditions")); return entityModel; }) @@ -215,16 +201,7 @@ public ResponseEntity getModelInvariants(@PathVariable String id) { // Implementation to be added return null; } - -// /** -// * Placeholder method to retrieve all pre/post conditions in a model -// */ -// @GetMapping("/model/{id}/prepostconditions") -// public ResponseEntity getModelPrePostConditions(@PathVariable String id) { -// // Implementation to be added -// return null; -// } - + /* Endpoints that are needed (prefix /api): POST /model - Create a new model diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java b/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java deleted file mode 100644 index 362da0816..000000000 --- a/use-api/src/main/java/org/tzi/use/rest/controller/RestApiController.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.tzi.use.rest.controller; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.tzi.use.api.UseApiException; -import org.tzi.use.DTO.ClassDTO; -import org.tzi.use.rest.services.MClassRService; -import org.tzi.use.uml.mm.MInvalidModelException; - -import java.util.List; - -@Deprecated -@RestController -//@RequestMapping("/api") guidelines -public class RestApiController { - - @Autowired - private MClassRService mClassService; - - - @GetMapping("/classes") - public ResponseEntity> getMClasses() { - return ResponseEntity.ok(mClassService.getAllMCLass()); - } - - @PostMapping("/class") - public ResponseEntity createMClass(@RequestBody ClassDTO aClassDTO) { - try { - ClassDTO savedClassDTO = mClassService.saveMClass(aClassDTO); - return new ResponseEntity<>(savedClassDTO, HttpStatus.CREATED); - }catch (MInvalidModelException e) { - // Return a detailed error message for MInvalidModelException - return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); - } catch (UseApiException e) { - // Return a detailed error message for UseApiException - return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); - } - catch (Exception e) { - return new ResponseEntity<>(e.getMessage(),HttpStatus.BAD_REQUEST); - } - } -} From 4725caf3560cd28f1690cbd9fcc907941ec6bcd9 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 3 Oct 2025 20:33:57 +0200 Subject: [PATCH 064/148] better error handling with globalexceptionhandler now correct exception when no model name --- .../controller/GlobalExceptionHandler.java | 80 ++++++++ .../use/rest/controller/ModelController.java | 181 +++++++++--------- 2 files changed, 168 insertions(+), 93 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java b/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java new file mode 100644 index 000000000..d9a9e8887 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java @@ -0,0 +1,80 @@ +package org.tzi.use.rest.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import org.tzi.use.api.UseApiException; + +import java.time.LocalDateTime; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Global exception handler for the REST API. + * This follows Spring Boot best practices for centralized exception handling. + * Extends ResponseEntityExceptionHandler to leverage Spring's built-in exception handling. + */ +@ControllerAdvice +public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + + /** + * Handle IllegalArgumentException - typically thrown when invalid input is provided + * (e.g., model element without name) + * Returns 400 Bad Request + */ + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity handleIllegalArgumentException( + IllegalArgumentException ex, WebRequest request) { + + Map body = new LinkedHashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", HttpStatus.BAD_REQUEST.value()); + body.put("error", "Bad Request"); + body.put("message", ex.getMessage()); + body.put("path", request.getDescription(false).replace("uri=", "")); + + return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); + } + + /** + * Handle UseApiException - thrown by the USE API when operations fail + * Returns 400 Bad Request + */ + @ExceptionHandler(UseApiException.class) + public ResponseEntity handleUseApiException( + UseApiException ex, WebRequest request) { + + Map body = new LinkedHashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", HttpStatus.BAD_REQUEST.value()); + body.put("error", "Bad Request"); + body.put("message", ex.getMessage()); + body.put("path", request.getDescription(false).replace("uri=", "")); + + return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); + } + + /** + * Handle all other unexpected exceptions + * Returns 500 Internal Server Error + */ + @ExceptionHandler(Exception.class) + public ResponseEntity handleGenericException( + Exception ex, WebRequest request) { + + Map body = new LinkedHashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value()); + body.put("error", "Internal Server Error"); + body.put("message", "An unexpected error occurred"); + body.put("path", request.getDescription(false).replace("uri=", "")); + + // Log the full exception for debugging (in production, this goes to logs) + logger.error("Unexpected exception occurred", ex); + + return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 979585c65..07a076d3f 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -28,45 +28,38 @@ public class ModelController { * @return The created model with HATEOAS links */ @PostMapping("/model") - public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { - try { - System.out.println("bin ich hier drinne?"); - ModelDTO createdModel = modelService.createModel(modelDTO); - System.out.println("und hier?"); - - // Create an EntityModel (HATEOAS) with the response - EntityModel entityModel = EntityModel.of(createdModel); + public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) throws UseApiException { + ModelDTO createdModel = modelService.createModel(modelDTO); - // Add HATEOAS links - // Link to self - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(createdModel.getName())) - .withSelfRel()); + // Create an EntityModel (HATEOAS) with the response + EntityModel entityModel = EntityModel.of(createdModel); - // Link to get all classes in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(createdModel.getName())) - .withRel("classes")); + // Add HATEOAS links + // Link to self + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelById(createdModel.getName())) + .withSelfRel()); - // Link to get all associations in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(createdModel.getName())) - .withRel("associations")); + // Link to get all classes in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(createdModel.getName())) + .withRel("classes")); - // Link to get all invariants in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(createdModel.getName())) - .withRel("invariants")); + // Link to get all associations in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(createdModel.getName())) + .withRel("associations")); + // Link to get all invariants in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(createdModel.getName())) + .withRel("invariants")); - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); - } catch (UseApiException e) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } /** @@ -75,43 +68,38 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m * @return The model with HATEOAS links */ @GetMapping("/model/{id}") - public ResponseEntity> getModelById(@PathVariable String id) { - try { - ModelDTO model = modelService.getModelByName(id); + public ResponseEntity> getModelById(@PathVariable String id) throws UseApiException { + ModelDTO model = modelService.getModelByName(id); - // Create an EntityModel (HATEOAS) with the response - EntityModel entityModel = EntityModel.of(model); + // Create an EntityModel (HATEOAS) with the response + EntityModel entityModel = EntityModel.of(model); - // Add HATEOAS links - // Link to self - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(id)) - .withSelfRel()); - - // Link to get all classes in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(id)) - .withRel("classes")); + // Add HATEOAS links + // Link to self + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelById(id)) + .withSelfRel()); - // Link to get all associations in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(id)) - .withRel("associations")); + // Link to get all classes in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(id)) + .withRel("classes")); - // Link to get all invariants in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(id)) - .withRel("invariants")); + // Link to get all associations in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(id)) + .withRel("associations")); + // Link to get all invariants in this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(id)) + .withRel("invariants")); - return new ResponseEntity<>(entityModel, HttpStatus.OK); - } catch (UseApiException e) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } + return new ResponseEntity<>(entityModel, HttpStatus.OK); } /** @@ -127,30 +115,33 @@ public ResponseEntity>> getAllModels() { .map(model -> { EntityModel entityModel = EntityModel.of(model); - // Add self link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(model.getName())) - .withSelfRel()); - - // Add classes link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(model.getName())) - .withRel("classes")); - - // Add associations link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(model.getName())) - .withRel("associations")); - - // Add invariants link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(model.getName())) - .withRel("invariants")); - + try { + // Add self link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelById(model.getName())) + .withSelfRel()); + + // Add classes link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(model.getName())) + .withRel("classes")); + + // Add associations link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(model.getName())) + .withRel("associations")); + + // Add invariants link + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(model.getName())) + .withRel("invariants")); + } catch (UseApiException e) { + // This won't actually be thrown during link building + } return entityModel; }) @@ -167,10 +158,14 @@ public ResponseEntity>> getAllModels() { .withSelfRel()); // Add link to create a new model - collectionModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .createModel(null)) - .withRel("create-model")); + try { + collectionModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .createModel(null)) + .withRel("create-model")); + } catch (UseApiException e) { + // This won't actually be thrown during link building + } return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @@ -201,7 +196,7 @@ public ResponseEntity getModelInvariants(@PathVariable String id) { // Implementation to be added return null; } - + /* Endpoints that are needed (prefix /api): POST /model - Create a new model From 0c16dc75c6408aa5978e5dd0395de36d167c61ce Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 3 Oct 2025 20:40:05 +0200 Subject: [PATCH 065/148] no throws --- .../tzi/use/rest/controller/ModelController.java | 14 ++++---------- .../org/tzi/use/rest/services/ModelService.java | 5 ++--- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 07a076d3f..e1f3dad8f 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -28,7 +28,7 @@ public class ModelController { * @return The created model with HATEOAS links */ @PostMapping("/model") - public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) throws UseApiException { + public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO){ ModelDTO createdModel = modelService.createModel(modelDTO); // Create an EntityModel (HATEOAS) with the response @@ -68,7 +68,7 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m * @return The model with HATEOAS links */ @GetMapping("/model/{id}") - public ResponseEntity> getModelById(@PathVariable String id) throws UseApiException { + public ResponseEntity> getModelById(@PathVariable String id) { ModelDTO model = modelService.getModelByName(id); // Create an EntityModel (HATEOAS) with the response @@ -115,7 +115,6 @@ public ResponseEntity>> getAllModels() { .map(model -> { EntityModel entityModel = EntityModel.of(model); - try { // Add self link entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) @@ -139,9 +138,7 @@ public ResponseEntity>> getAllModels() { WebMvcLinkBuilder.methodOn(ModelController.class) .getModelInvariants(model.getName())) .withRel("invariants")); - } catch (UseApiException e) { - // This won't actually be thrown during link building - } + return entityModel; }) @@ -158,14 +155,11 @@ public ResponseEntity>> getAllModels() { .withSelfRel()); // Add link to create a new model - try { collectionModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) .createModel(null)) .withRel("create-model")); - } catch (UseApiException e) { - // This won't actually be thrown during link building - } + return new ResponseEntity<>(collectionModel, HttpStatus.OK); } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index ec0ff06c9..38185868b 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -28,7 +28,7 @@ public class ModelService { * @return The created model with assigned ID * @throws UseApiException If there's an error creating the model */ - public ModelDTO createModel(ModelDTO modelDTOreq) throws UseApiException { + public ModelDTO createModel(ModelDTO modelDTOreq){ ModelNTT tmp_modelntt = modelMapper.toEntity(modelDTOreq); UseModelApi modelApi = UseModelFacade.createModel(tmp_modelntt.getName()); @@ -40,11 +40,10 @@ public ModelDTO createModel(ModelDTO modelDTOreq) throws UseApiException { /** * Retrieves a model by its ID * - * @param id The ID of the model to retrieve * @return The model DTO * @throws UseApiException If the model is not found */ - public ModelDTO getModelByName(String name) throws UseApiException { + public ModelDTO getModelByName(String name) { Optional tmp_modelntt = modelRepo.findById(name); ModelDTO tmp_modeldto = modelMapper.toDTO(tmp_modelntt.get()); return tmp_modeldto; From 2358aa397a5cbec6e70f4db0a3c0bbe44190dee1 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 3 Oct 2025 21:23:53 +0200 Subject: [PATCH 066/148] error handling for dup --- .../rest/controller/GlobalExceptionHandler.java | 16 ++++++++++++++++ .../org/tzi/use/rest/services/ModelService.java | 8 +++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java b/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java index d9a9e8887..c69a9d7fc 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java @@ -1,5 +1,6 @@ package org.tzi.use.rest.controller; +import org.springframework.dao.DuplicateKeyException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -39,6 +40,21 @@ public ResponseEntity handleIllegalArgumentException( return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); } + + @ExceptionHandler(DuplicateKeyException.class) + public ResponseEntity handleDuplicateKeyException( + DuplicateKeyException ex, WebRequest request) { + + Map body = new LinkedHashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", HttpStatus.CONFLICT.value()); + body.put("error", "Conflict"); + body.put("message", ex.getMessage()); + body.put("path", request.getDescription(false).replace("uri=", "")); + + return new ResponseEntity<>(body, HttpStatus.CONFLICT); + } + /** * Handle UseApiException - thrown by the USE API when operations fail * Returns 400 Bad Request diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 38185868b..d3504c758 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -1,6 +1,7 @@ package org.tzi.use.rest.services; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.tzi.use.DTO.ModelDTO; import org.tzi.use.UseModelFacade; @@ -29,10 +30,12 @@ public class ModelService { * @throws UseApiException If there's an error creating the model */ public ModelDTO createModel(ModelDTO modelDTOreq){ + if(modelRepo.findById(modelDTOreq.getName()).isPresent()) { + throw new DuplicateKeyException("Model name already exists"); + } ModelNTT tmp_modelntt = modelMapper.toEntity(modelDTOreq); UseModelApi modelApi = UseModelFacade.createModel(tmp_modelntt.getName()); - // Save to repository modelRepo.save(tmp_modelntt); return modelMapper.toDTO(tmp_modelntt); } @@ -45,8 +48,7 @@ public ModelDTO createModel(ModelDTO modelDTOreq){ */ public ModelDTO getModelByName(String name) { Optional tmp_modelntt = modelRepo.findById(name); - ModelDTO tmp_modeldto = modelMapper.toDTO(tmp_modelntt.get()); - return tmp_modeldto; + return modelMapper.toDTO(tmp_modelntt.get()); } /** From e6d47da577c2242e9c42f9212f1812c21118ed03 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 3 Oct 2025 21:24:48 +0200 Subject: [PATCH 067/148] unresolved thought --- use-api/src/main/java/org/tzi/use/UseModelFacade.java | 1 + 1 file changed, 1 insertion(+) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index cc0dc96b3..e0a55c52c 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -10,6 +10,7 @@ public class UseModelFacade { private static final UseModelApi useModelApi = new UseModelApi(); public static UseModelApi createModel(String modelName) { + useModelApi.createModel(modelName); return new UseModelApi(modelName); } From e5aeaae34c382414b867ae3269f8c4526a9a27fc Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 5 Oct 2025 18:21:00 +0200 Subject: [PATCH 068/148] Refactor controllers and services for model API Renamed GlobalExceptionHandler and updated its package. Refactored ModelController and ModelService to use Lombok's @RequiredArgsConstructor for dependency injection. Changed model endpoints to use 'name' instead of 'id' for path variables, updated HATEOAS links, and added placeholder methods for class, association, and invariant endpoints. Added a stub for RestExceptionHandler. --- .../GlobalExceptionHandler.java | 2 +- .../use/rest/controller/ModelController.java | 53 +++++++++++-------- .../rest/exception/RestExceptionHandler.java | 1 + .../tzi/use/rest/services/ModelService.java | 41 +++++++++----- 4 files changed, 61 insertions(+), 36 deletions(-) rename use-api/src/main/java/org/tzi/use/{rest/controller => }/GlobalExceptionHandler.java (99%) create mode 100644 use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java b/use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java similarity index 99% rename from use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java rename to use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java index c69a9d7fc..0d47155c7 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/GlobalExceptionHandler.java +++ b/use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java @@ -1,4 +1,4 @@ -package org.tzi.use.rest.controller; +package org.tzi.use; import org.springframework.dao.DuplicateKeyException; import org.springframework.http.HttpStatus; diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index e1f3dad8f..d8d11a27f 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -1,6 +1,6 @@ package org.tzi.use.rest.controller; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -9,7 +9,6 @@ import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.tzi.use.DTO.ModelDTO; -import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ModelService; import java.util.List; @@ -17,10 +16,13 @@ @RestController @RequestMapping("/api") +@RequiredArgsConstructor public class ModelController { - @Autowired - private ModelService modelService; + // No need for @Autowired with @RequiredArgsConstructor + // because Lombok generates a constructor for final fields + // and Spring will use that constructor for dependency injection + private final ModelService modelService; /** * Create a new model @@ -38,7 +40,7 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m // Link to self entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(createdModel.getName())) + .getModelByName(createdModel.getName())) .withSelfRel()); // Link to get all classes in this model @@ -64,12 +66,12 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m /** * Retrieve a model by its ID - * @param id The ID of the model to retrieve + * @param name The ID of the model to retrieve * @return The model with HATEOAS links */ - @GetMapping("/model/{id}") - public ResponseEntity> getModelById(@PathVariable String id) { - ModelDTO model = modelService.getModelByName(id); + @GetMapping("/model/{name}") + public ResponseEntity> getModelByName(@PathVariable String name) { + ModelDTO model = modelService.getModelByName(name); // Create an EntityModel (HATEOAS) with the response EntityModel entityModel = EntityModel.of(model); @@ -78,25 +80,25 @@ public ResponseEntity> getModelById(@PathVariable String i // Link to self entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(id)) + .getModelByName(name)) .withSelfRel()); // Link to get all classes in this model entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(id)) + .getModelClasses(name)) .withRel("classes")); // Link to get all associations in this model entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(id)) + .getModelAssociations(name)) .withRel("associations")); // Link to get all invariants in this model entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(id)) + .getModelInvariants(name)) .withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.OK); @@ -118,7 +120,7 @@ public ResponseEntity>> getAllModels() { // Add self link entityModel.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelById(model.getName())) + .getModelByName(model.getName())) .withSelfRel()); // Add classes link @@ -164,11 +166,17 @@ public ResponseEntity>> getAllModels() { return new ResponseEntity<>(collectionModel, HttpStatus.OK); } + @PostMapping("/model/{name}/class") + public ResponseEntity get(@PathVariable String name) { + // Implementation to be added + return null; + } + /** * Placeholder method to retrieve all classes in a model */ - @GetMapping("/model/{id}/classes") - public ResponseEntity getModelClasses(@PathVariable String id) { + @GetMapping("/model/{name}/classes") + public ResponseEntity getModelClasses(@PathVariable String name) { // Implementation to be added return null; } @@ -176,8 +184,8 @@ public ResponseEntity getModelClasses(@PathVariable String id) { /** * Placeholder method to retrieve all associations in a model */ - @GetMapping("/model/{id}/associations") - public ResponseEntity getModelAssociations(@PathVariable String id) { + @GetMapping("/model/{name}/associations") + public ResponseEntity getModelAssociations(@PathVariable String name) { // Implementation to be added return null; } @@ -185,20 +193,21 @@ public ResponseEntity getModelAssociations(@PathVariable String id) { /** * Placeholder method to retrieve all invariants in a model */ - @GetMapping("/model/{id}/invariants") - public ResponseEntity getModelInvariants(@PathVariable String id) { + @GetMapping("/model/{name}/invariants") + public ResponseEntity getModelInvariants(@PathVariable String name) { // Implementation to be added return null; } /* Endpoints that are needed (prefix /api): - POST /model - Create a new model + POST /model - Create a new model :check: POST /model/class - Add a new class to a model + POST /model/association - Add a new association to a model + POST /model/invariant - Add a new invariant to a model GET /model/{id} - Retrieve a model by ID GET /model/{id}/classes - Retrieve all classes in a model GET /model/{id}/associations - Retrieve all association in a model GET /model/{id}/invariants - Retrieve all invariants in a model - GET /model/{id}/prepostconditions - Retrieve all pre- / post-conditions in a model */ } diff --git a/use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java b/use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java @@ -0,0 +1 @@ + diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index d3504c758..7e04381a8 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -1,12 +1,14 @@ package org.tzi.use.rest.services; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; +import org.tzi.use.DTO.AssociationDTO; +import org.tzi.use.DTO.ClassDTO; +import org.tzi.use.DTO.InvariantDTO; import org.tzi.use.DTO.ModelDTO; import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; -import org.tzi.use.api.UseModelApi; import org.tzi.use.entities.ModelNTT; import org.tzi.use.mapper.ModelMapper; import org.tzi.use.repository.ModelRepo; @@ -15,11 +17,11 @@ import java.util.Optional; @Service +@RequiredArgsConstructor public class ModelService { - @Autowired - private ModelRepo modelRepo; - @Autowired - private ModelMapper modelMapper; + + private final ModelRepo modelRepo; + private final ModelMapper modelMapper; /** @@ -29,12 +31,13 @@ public class ModelService { * @return The created model with assigned ID * @throws UseApiException If there's an error creating the model */ - public ModelDTO createModel(ModelDTO modelDTOreq){ - if(modelRepo.findById(modelDTOreq.getName()).isPresent()) { + public ModelDTO createModel(ModelDTO modelDTOreq) { + if (modelRepo.findById(modelDTOreq.getName()).isPresent()) { throw new DuplicateKeyException("Model name already exists"); } ModelNTT tmp_modelntt = modelMapper.toEntity(modelDTOreq); - UseModelApi modelApi = UseModelFacade.createModel(tmp_modelntt.getName()); + + UseModelFacade.createModel(tmp_modelntt.getName()); modelRepo.save(tmp_modelntt); return modelMapper.toDTO(tmp_modelntt); @@ -57,9 +60,21 @@ public ModelDTO getModelByName(String name) { * @return List of all model DTOs */ public List getAllModels() { - return modelRepo.findAll() - .stream() - .map(modelMapper::toDTO) - .toList(); + return modelRepo.findAll().stream().map(modelMapper::toDTO).toList(); + } + + public List getModelClasses() { + // implement later + return null; + } + + public List getModelAssociations() { + // implement later + return null; + } + + public List getModelInvariants () { + // implement later + return null; } } From 03edbb3774e40463d3709dcf7d1b07e9d1bb4fd5 Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 5 Oct 2025 19:42:36 +0200 Subject: [PATCH 069/148] clean up the dtos and better classdto --- .../main/java/org/tzi/use/DTO/ClassDTO.java | 57 ++----------------- .../main/java/org/tzi/use/DTO/ModelDTO.java | 4 -- 2 files changed, 4 insertions(+), 57 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index 2c1f7563a..e9d194f5f 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -1,66 +1,17 @@ package org.tzi.use.DTO; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; -import org.springframework.data.mongodb.core.mapping.DBRef; -import lombok.Data; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.AllArgsConstructor; +import lombok.*; import java.util.ArrayList; import java.util.List; -@Document @Data @NoArgsConstructor @AllArgsConstructor -@Builder public class ClassDTO { - @Id - private String id; private String name; - - @DBRef - @Builder.Default - private List attributeDTOS = new ArrayList<>(); - - @DBRef - @Builder.Default - private List operationDTOS = new ArrayList<>(); - - public void addAttribute(AttributeDTO attributeDTO) { - attributeDTOS.add(attributeDTO); - } - - public void removeAttribute(AttributeDTO attributeDTO) { - attributeDTOS.remove(attributeDTO); - } - - public void addOperation(OperationDTO operationDTO) { - operationDTOS.add(operationDTO); - } - - public void removeOperation(OperationDTO operationDTO) { - operationDTOS.remove(operationDTO); - } - - // Additional constructor - public ClassDTO(String id, String name, AttributeDTO attributes, OperationDTO operations) { - this.id = id; - this.name = name; - this.attributeDTOS = new ArrayList<>(); - this.operationDTOS = new ArrayList<>(); - if (attributes != null) this.attributeDTOS.add(attributes); - if (operations != null) this.operationDTOS.add(operations); - } - - // Convenience constructor - public ClassDTO(String id, String name) { - this.id = id; - this.name = name; - this.attributeDTOS = new ArrayList<>(); - this.operationDTOS = new ArrayList<>(); - } + private List attributes = new ArrayList<>(); + private List operations = new ArrayList<>(); + private List associations = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index 872afd5a9..27fcbe6bd 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -7,16 +7,12 @@ @Data @AllArgsConstructor -//@RequiredArgsConstructor @NoArgsConstructor public class ModelDTO { private String name; -// private String id; private List classes = new ArrayList<>(); private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); -// private List preConditions = new ArrayList<>(); -// private List postConditions = new ArrayList<>(); public ModelDTO(String name) { this.name = name; From 08ebace59b2bb9f576a1400b4c75481c36d6e575 Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 5 Oct 2025 19:45:56 +0200 Subject: [PATCH 070/148] depr. associations --- use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java | 2 +- use-api/src/main/java/org/tzi/use/entities/ModelNTT.java | 2 +- .../main/java/org/tzi/use/rest/controller/ModelController.java | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index e9d194f5f..f387a8ad3 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -13,5 +13,5 @@ public class ClassDTO { private String name; private List attributes = new ArrayList<>(); private List operations = new ArrayList<>(); - private List associations = new ArrayList<>(); +// private List associations = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index 4ed25afc7..dc4f770ac 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -20,7 +20,7 @@ public class ModelNTT { @Id private String name; private List classes = new ArrayList<>(); - private List associations = new ArrayList<>(); +// private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); public ModelNTT(String name) { diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index d8d11a27f..8cac3a0e9 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -181,7 +181,9 @@ public ResponseEntity getModelClasses(@PathVariable String name) { return null; } + @Deprecated /** + * Deprecated for now * Placeholder method to retrieve all associations in a model */ @GetMapping("/model/{name}/associations") From b5b9ef79559bab17093db69b23f88c4a03cd70fe Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 5 Oct 2025 20:09:16 +0200 Subject: [PATCH 071/148] Refactor DTOs and add ClassNTT entity Added new ClassNTT entity with MongoDB mapping --- .../java/org/tzi/use/DTO/AttributeDTO.java | 21 ++-------------- .../java/org/tzi/use/DTO/OperationDTO.java | 22 +---------------- .../java/org/tzi/use/entities/ClassNTT.java | 24 +++++++++++++++++++ 3 files changed, 27 insertions(+), 40 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/entities/ClassNTT.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java index cb6e9c599..8640f9a3c 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AttributeDTO.java @@ -1,32 +1,15 @@ package org.tzi.use.DTO; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; import lombok.Data; -import lombok.Builder; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; -@Document @Data @NoArgsConstructor @AllArgsConstructor -@Builder public class AttributeDTO { - @Id - private String id; + private String name; private String type; - - // Constructors for backward compatibility - public AttributeDTO(String name, String type){ - this.name = name; - this.type = type; - } - - public AttributeDTO(String id, String name, String type, ClassDTO mclass) { - this.id = id; - this.name = name; - this.type = type; - } + } diff --git a/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java index 4aebec1ed..b6ca09af9 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java @@ -1,35 +1,15 @@ package org.tzi.use.DTO; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; import lombok.Data; -import lombok.Builder; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; -@Document @Data @NoArgsConstructor @AllArgsConstructor -@Builder public class OperationDTO { - @Id - private String id; + private String name; private String body; - // Constructors for backward compatibility - public OperationDTO(String name, String body) { - this.name = name; - this.body = body; - } - - public OperationDTO(String id, String name, ClassDTO mclass) { - this.id = id; - this.name = name; - } - - public OperationDTO(String name) { - this.name = name; - } } diff --git a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java new file mode 100644 index 000000000..58c13d77a --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java @@ -0,0 +1,24 @@ +package org.tzi.use.entities; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.tzi.use.DTO.AttributeDTO; +import org.tzi.use.DTO.OperationDTO; + +import java.util.ArrayList; +import java.util.List; + +@Document("class") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ClassNTT { + @Id + private String name; + private List attributes = new ArrayList<>(); + private List operations = new ArrayList<>(); +// private List associations = new ArrayList<>(); +} From 862f52d9bcf9b66ed097d2fdd2a145080d9995ed Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 6 Oct 2025 16:15:22 +0200 Subject: [PATCH 072/148] Refactor class creation and mapping logic Introduced ClassMapper for DTO/entity conversion and updated ClassRepo to use ClassNTT. Removed deprecated MClassRService and moved class creation logic to ModelService. Added associations to ClassDTO and ClassNTT. Updated ModelController to use new class creation endpoint. --- .../main/java/org/tzi/use/DTO/ClassDTO.java | 2 +- .../main/java/org/tzi/use/UseModelFacade.java | 31 ++++-------------- .../java/org/tzi/use/entities/ClassNTT.java | 3 +- .../java/org/tzi/use/mapper/ClassMapper.java | 14 ++++++++ .../org/tzi/use/repository/ClassRepo.java | 4 +-- .../use/rest/controller/ModelController.java | 8 +++-- .../tzi/use/rest/services/MClassRService.java | 32 ------------------- .../tzi/use/rest/services/ModelService.java | 19 +++++++++++ 8 files changed, 50 insertions(+), 63 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/mapper/ClassMapper.java delete mode 100644 use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index f387a8ad3..e9d194f5f 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -13,5 +13,5 @@ public class ClassDTO { private String name; private List attributes = new ArrayList<>(); private List operations = new ArrayList<>(); -// private List associations = new ArrayList<>(); + private List associations = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index e0a55c52c..3d978bfff 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -3,38 +3,19 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.DTO.*; -import org.tzi.use.uml.mm.MClass; +import org.tzi.use.entities.ClassNTT; +import org.tzi.use.entities.ModelNTT; import org.tzi.use.uml.mm.MInvalidModelException; public class UseModelFacade { private static final UseModelApi useModelApi = new UseModelApi(); - public static UseModelApi createModel(String modelName) { + public static void createModel(String modelName) { useModelApi.createModel(modelName); - return new UseModelApi(modelName); } - @Deprecated - public static ClassDTO createMClass(ClassDTO aClass) throws UseApiException, MInvalidModelException { -// MClass mClass; -// mClass = useModelApi.createClass(aClass.getName_mclass(), false); -// for (AttributeDTO attributeDTO : aClass.getAttributes()) { -// useModelApi.createAttribute(mClass.name(), attributeDTO.getName_attr(), attributeDTO.getType()); -// -// } -// //parameter liste wird noch nicht unterstützt. -> daher new String [][] -// for (OperationDTO operationDTO : aClass.getOperations()) { -// useModelApi.createOperation(mClass.name(), operationDTO.getName(), new String[0][0], operationDTO.getBody()); -// } -// -// for(PrePostConditionDTO prePostConditionDTO : aClass.getPrePostConditions()) { -// useModelApi.createPrePostCondition(mClass.name(), prePostConditionDTO.getOperationName(), prePostConditionDTO.getName(), prePostConditionDTO.getCondition(), prePostConditionDTO.isPre()); -// } -// -// for (InvariantDTO invariantDTO : aClass.getInvariants()) { -// useModelApi.createInvariant(mClass.name(), invariantDTO.getInvName(), invariantDTO.getInvBody(), invariantDTO.isExistential()); -// } -// - return null; + + public static void createClass(String className) throws UseApiException { + useModelApi.createClass(className, false); } } diff --git a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java index 58c13d77a..0bde58db1 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java @@ -5,6 +5,7 @@ import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import org.tzi.use.DTO.AssociationDTO; import org.tzi.use.DTO.AttributeDTO; import org.tzi.use.DTO.OperationDTO; @@ -20,5 +21,5 @@ public class ClassNTT { private String name; private List attributes = new ArrayList<>(); private List operations = new ArrayList<>(); -// private List associations = new ArrayList<>(); + private List associations = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/mapper/ClassMapper.java b/use-api/src/main/java/org/tzi/use/mapper/ClassMapper.java new file mode 100644 index 000000000..bdd664046 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/ClassMapper.java @@ -0,0 +1,14 @@ +package org.tzi.use.mapper; + + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.ClassDTO; +import org.tzi.use.entities.ClassNTT; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface ClassMapper { + ClassDTO toDTO(ClassNTT entity); + + ClassNTT toEntity(ClassDTO dto); +} diff --git a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java index 72974c0db..96cc3cb0a 100644 --- a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java +++ b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java @@ -1,7 +1,7 @@ package org.tzi.use.repository; import org.springframework.data.mongodb.repository.MongoRepository; -import org.tzi.use.DTO.ClassDTO; +import org.tzi.use.entities.ClassNTT; -public interface ClassRepo extends MongoRepository { +public interface ClassRepo extends MongoRepository { } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 8cac3a0e9..0d61e1e1b 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -8,7 +8,9 @@ import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ModelService; import java.util.List; @@ -167,8 +169,10 @@ public ResponseEntity>> getAllModels() { } @PostMapping("/model/{name}/class") - public ResponseEntity get(@PathVariable String name) { - // Implementation to be added + public ResponseEntity get(@RequestBody ClassDTO classDTO) throws UseApiException { + ClassDTO createdClass = modelService.createClass(classDTO); + + return null; } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java b/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java deleted file mode 100644 index 1fc0e6744..000000000 --- a/use-api/src/main/java/org/tzi/use/rest/services/MClassRService.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.tzi.use.rest.services; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.tzi.use.UseModelFacade; -import org.tzi.use.api.UseApiException; -import org.tzi.use.DTO.ClassDTO; -import org.tzi.use.repository.ClassRepo; -import org.tzi.use.uml.mm.MInvalidModelException; - -import java.util.List; - -@Service -public class MClassRService { - - @Autowired - private ClassRepo classRepository; - - @Deprecated - public ClassDTO saveMClass(ClassDTO aClassDTO) throws MInvalidModelException, UseApiException { - UseModelFacade.createMClass(aClassDTO); -// if(classRepository.findById(aClassDTO.getName_mclass()).isPresent()) { -// // TODO Exception already exists -// throw new UseApiException("Class name already exists"); -// } - return classRepository.save(aClassDTO); - } - - public List getAllMCLass(){ - return classRepository.findAll(); - } -} \ No newline at end of file diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 7e04381a8..f92750bd6 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -9,8 +9,11 @@ import org.tzi.use.DTO.ModelDTO; import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; +import org.tzi.use.entities.ClassNTT; import org.tzi.use.entities.ModelNTT; +import org.tzi.use.mapper.ClassMapperImpl; import org.tzi.use.mapper.ModelMapper; +import org.tzi.use.repository.ClassRepo; import org.tzi.use.repository.ModelRepo; import java.util.List; @@ -21,7 +24,9 @@ public class ModelService { private final ModelRepo modelRepo; + private final ClassRepo classRepo; private final ModelMapper modelMapper; + private final ClassMapperImpl classMapperImpl; /** @@ -43,6 +48,20 @@ public ModelDTO createModel(ModelDTO modelDTOreq) { return modelMapper.toDTO(tmp_modelntt); } + public ClassDTO createClass(ClassDTO classDTOreq) throws UseApiException { + if(classRepo.findById(classDTOreq.getName()).isPresent()) { + throw new DuplicateKeyException("Class name already exists"); + } + + ClassNTT tmp_classntt = classMapperImpl.toEntity(classDTOreq); + + UseModelFacade.createClass(tmp_classntt.getName()); + + classRepo.save(tmp_classntt); + return classMapperImpl.toDTO(tmp_classntt); + + } + /** * Retrieves a model by its ID * From 67d8318eee5a80dee5f50ffb6df9acd60be8b6a6 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 6 Oct 2025 18:46:03 +0200 Subject: [PATCH 073/148] model now has a class when a class is added --- .../java/org/tzi/use/entities/ModelNTT.java | 25 +++++++++++- .../use/rest/controller/ModelController.java | 39 +++++++++++++++++-- .../tzi/use/rest/services/ModelService.java | 8 +++- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index dc4f770ac..b970afe96 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -3,7 +3,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import org.tzi.use.DTO.ClassDTO; @@ -19,11 +18,33 @@ public class ModelNTT { @Id private String name; - private List classes = new ArrayList<>(); + private List classes = new ArrayList<>(); // private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); public ModelNTT(String name) { this.name = name; } + + + public void addClass(ClassNTT classDTO) { + if (classDTO == null) { + return; + } + if (this.classes == null) { + this.classes = new ArrayList<>(); + } + this.classes.add(classDTO); + } + + public void addInvariant(String invariant) { + if (invariant == null || invariant.trim().isEmpty()) { + return; + } + if (this.invariants == null) { + this.invariants = new ArrayList<>(); + } + this.invariants.add(invariant); + } + } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 0d61e1e1b..ce5349e24 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -168,12 +168,43 @@ public ResponseEntity>> getAllModels() { return new ResponseEntity<>(collectionModel, HttpStatus.OK); } - @PostMapping("/model/{name}/class") - public ResponseEntity get(@RequestBody ClassDTO classDTO) throws UseApiException { - ClassDTO createdClass = modelService.createClass(classDTO); + @PostMapping("/model/{modelName}/class") + public ResponseEntity> createClass(@PathVariable String modelName, @RequestBody ClassDTO classDTO) throws UseApiException { + ClassDTO createdClass = modelService.createClass(modelName, classDTO); + // Wrap the created class in an EntityModel for HATEOAS + EntityModel entityModel = EntityModel.of(createdClass); - return null; + // Link to the parent model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelByName(modelName)) + .withRel("model")); + + // Link to the classes listing for this model (also used as self since there's no single-class GET) + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(modelName)) + .withSelfRel()); + + // Link to create another class in this model + entityModel.add(WebMvcLinkBuilder.linkTo(ModelController.class) + .slash("model").slash(modelName).slash("class") + .withRel("create-class")); + + // Link to associations for this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(modelName)) + .withRel("associations")); + + // Link to invariants for this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(modelName)) + .withRel("invariants")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } /** diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index f92750bd6..4bbcb5846 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -48,15 +48,20 @@ public ModelDTO createModel(ModelDTO modelDTOreq) { return modelMapper.toDTO(tmp_modelntt); } - public ClassDTO createClass(ClassDTO classDTOreq) throws UseApiException { + public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseApiException { if(classRepo.findById(classDTOreq.getName()).isPresent()) { throw new DuplicateKeyException("Class name already exists"); } ClassNTT tmp_classntt = classMapperImpl.toEntity(classDTOreq); + Optional modelOfClass = modelRepo.findById(modelName); + //check for modelOfClass presence is nessary? -> I think no because cannot create model via api if it doesn't exist + + modelOfClass.get().addClass(tmp_classntt); UseModelFacade.createClass(tmp_classntt.getName()); + modelRepo.save(modelOfClass.get()); classRepo.save(tmp_classntt); return classMapperImpl.toDTO(tmp_classntt); @@ -69,6 +74,7 @@ public ClassDTO createClass(ClassDTO classDTOreq) throws UseApiException { * @throws UseApiException If the model is not found */ public ModelDTO getModelByName(String name) { + //isnt it a better practice to map it to a ntt first and then do the findBy? Optional tmp_modelntt = modelRepo.findById(name); return modelMapper.toDTO(tmp_modelntt.get()); } From 15ec95651290ec571e38cd484e25a864c913dcde Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 16 Oct 2025 18:22:34 +0200 Subject: [PATCH 074/148] get all classes endpoint --- .../use/rest/controller/ModelController.java | 72 +++++++++++++++++-- .../tzi/use/rest/services/ModelService.java | 8 ++- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index ce5349e24..a10f9f682 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -210,12 +210,76 @@ public ResponseEntity> createClass(@PathVariable String mo /** * Placeholder method to retrieve all classes in a model */ - @GetMapping("/model/{name}/classes") - public ResponseEntity getModelClasses(@PathVariable String name) { - // Implementation to be added - return null; + @GetMapping("/model/{modelName}/classes") + public ResponseEntity getModelClasses(@PathVariable String modelName) { + List modelClasses = modelService.getModelClasses(modelName); + + // Convert each class to an EntityModel with links + List> classEntities = modelClasses.stream() + .map(classDTO -> { + EntityModel entityModel = EntityModel.of(classDTO); + + // Link to the parent model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelByName(modelName)) + .withRel("model")); + + // Link to this classes collection (self) + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(modelName)) + .withSelfRel()); + + // Link to create another class + try { + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .createClass(modelName, null)) + .withRel("create-class")); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + + // Link to associations + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(modelName)) + .withRel("associations")); + + // Link to invariants + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(modelName)) + .withRel("invariants")); + + return entityModel; + }) + .collect(Collectors.toList()); + + // Create a CollectionModel + CollectionModel> collectionModel = CollectionModel.of(classEntities); + + // Add self-link to the collection + collectionModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(modelName)) + .withSelfRel()); + + // Add link to create a new class + try { + collectionModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .createClass(modelName, null)) + .withRel("create-class")); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + + return new ResponseEntity<>(collectionModel, HttpStatus.OK); } + @Deprecated /** * Deprecated for now diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 4bbcb5846..e8450c696 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -88,9 +88,11 @@ public List getAllModels() { return modelRepo.findAll().stream().map(modelMapper::toDTO).toList(); } - public List getModelClasses() { - // implement later - return null; + public List getModelClasses(String modelName){ + Optional modelOpt = modelRepo.findById(modelName); + return modelOpt.get().getClasses().stream() + .map(classMapperImpl::toDTO) + .toList(); } public List getModelAssociations() { From 893861ef42f30e6c30b0e3cb63faaa847d237229 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 16 Oct 2025 20:16:50 +0200 Subject: [PATCH 075/148] corrected Invariant and PrePostCond --- .../java/org/tzi/use/DTO/InvariantDTO.java | 41 +++------------ .../main/java/org/tzi/use/DTO/ModelDTO.java | 3 +- .../org/tzi/use/DTO/PrePostConditionDTO.java | 52 +++---------------- .../org/tzi/use/entities/InvariantNTT.java | 18 +++++++ .../java/org/tzi/use/entities/ModelNTT.java | 12 +---- .../tzi/use/entities/PrePostConditionNTT.java | 18 +++++++ .../org/tzi/use/mapper/InvariantMapper.java | 14 +++++ .../use/mapper/PrePostConditionMapper.java | 13 +++++ 8 files changed, 79 insertions(+), 92 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/mapper/InvariantMapper.java create mode 100644 use-api/src/main/java/org/tzi/use/mapper/PrePostConditionMapper.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java b/use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java index 238c4aae5..5a4d51a05 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/InvariantDTO.java @@ -1,45 +1,16 @@ package org.tzi.use.DTO; -import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +@Data +@NoArgsConstructor +@AllArgsConstructor public class InvariantDTO { - @Id private String invName; private String invBody; private boolean isExistential; - public InvariantDTO() { - - } - - public InvariantDTO(String invName, String invBody, boolean isExistential) { - this.invName = invName; - this.invBody = invBody; - this.isExistential = isExistential; - } - - public String getInvName() { - return invName; - } - - public String getInvBody() { - return invBody; - } - - public boolean isExistential() { - return isExistential; - } - - public void setInvName(String invName) { - this.invName = invName; - } - - public void setInvBody(String invBody) { - this.invBody = invBody; - } - - public void setExistential(boolean existential) { - isExistential = existential; - } } diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index 27fcbe6bd..e64e56024 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -1,6 +1,7 @@ package org.tzi.use.DTO; import lombok.*; +import org.tzi.use.entities.InvariantNTT; import java.util.ArrayList; import java.util.List; @@ -12,7 +13,7 @@ public class ModelDTO { private String name; private List classes = new ArrayList<>(); private List associations = new ArrayList<>(); - private List invariants = new ArrayList<>(); + private List invariants = new ArrayList<>(); public ModelDTO(String name) { this.name = name; diff --git a/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java b/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java index ccdb9026c..2ff38621d 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java @@ -1,57 +1,19 @@ package org.tzi.use.DTO; import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import org.springframework.data.mongodb.core.mapping.Document; -@Document +@Data +@NoArgsConstructor +@AllArgsConstructor public class PrePostConditionDTO { - @Id + private String operationName; private String name; private String condition; private boolean isPre; - public PrePostConditionDTO() { - } - - public PrePostConditionDTO(String operationName, String name, String condition, boolean isPre) { - this.operationName = operationName; - this.name = name; - this.condition = condition; - this.isPre = isPre; - - - } - - public String getOperationName() { - return operationName; - } - - public void setOperationName(String operationName) { - this.operationName = operationName; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCondition() { - return condition; - } - - public void setCondition(String condition) { - this.condition = condition; - } - - public boolean isPre() { - return isPre; - } - - public void setPre(boolean pre) { - isPre = pre; - } } diff --git a/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java b/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java new file mode 100644 index 000000000..45fa94115 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java @@ -0,0 +1,18 @@ +package org.tzi.use.entities; + +import org.springframework.data.annotation.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document("invariant") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class InvariantNTT { + @Id + private String invName; + private String invBody; + private boolean isExistential; +} diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index b970afe96..fba86463f 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -20,7 +20,7 @@ public class ModelNTT { private String name; private List classes = new ArrayList<>(); // private List associations = new ArrayList<>(); - private List invariants = new ArrayList<>(); + private List invariants = new ArrayList<>(); public ModelNTT(String name) { this.name = name; @@ -37,14 +37,4 @@ public void addClass(ClassNTT classDTO) { this.classes.add(classDTO); } - public void addInvariant(String invariant) { - if (invariant == null || invariant.trim().isEmpty()) { - return; - } - if (this.invariants == null) { - this.invariants = new ArrayList<>(); - } - this.invariants.add(invariant); - } - } diff --git a/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java b/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java new file mode 100644 index 000000000..dafafe2dd --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java @@ -0,0 +1,18 @@ +package org.tzi.use.entities; + +import org.springframework.data.annotation.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document("prepostcondition") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class PrePostConditionNTT { + private String operationName; + private String name; + private String condition; + private boolean isPre; +} diff --git a/use-api/src/main/java/org/tzi/use/mapper/InvariantMapper.java b/use-api/src/main/java/org/tzi/use/mapper/InvariantMapper.java new file mode 100644 index 000000000..ec9931cbc --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/InvariantMapper.java @@ -0,0 +1,14 @@ +package org.tzi.use.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.InvariantDTO; +import org.tzi.use.entities.InvariantNTT; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) + +public interface InvariantMapper { + InvariantDTO toDTO(InvariantNTT entity); + + InvariantNTT toEntity(InvariantDTO dto); +} diff --git a/use-api/src/main/java/org/tzi/use/mapper/PrePostConditionMapper.java b/use-api/src/main/java/org/tzi/use/mapper/PrePostConditionMapper.java new file mode 100644 index 000000000..ca571acd6 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/PrePostConditionMapper.java @@ -0,0 +1,13 @@ +package org.tzi.use.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.PrePostConditionDTO; +import org.tzi.use.entities.PrePostConditionNTT; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface PrePostConditionMapper { + PrePostConditionDTO toDTO(PrePostConditionNTT entity); + + PrePostConditionNTT toEntity(PrePostConditionDTO dto); +} From bdf654085dbad43a60cd622ffbcc59222ac3ff15 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 16 Oct 2025 20:17:03 +0200 Subject: [PATCH 076/148] service invar --- .../org/tzi/use/rest/controller/ModelController.java | 2 +- .../java/org/tzi/use/rest/services/ModelService.java | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index a10f9f682..592eba5b4 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -295,7 +295,7 @@ public ResponseEntity getModelAssociations(@PathVariable String name) { * Placeholder method to retrieve all invariants in a model */ @GetMapping("/model/{name}/invariants") - public ResponseEntity getModelInvariants(@PathVariable String name) { + public ResponseEntity getModelInvariants(@PathVariable String modelName) { // Implementation to be added return null; } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index e8450c696..bbae1f3e9 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -12,6 +12,7 @@ import org.tzi.use.entities.ClassNTT; import org.tzi.use.entities.ModelNTT; import org.tzi.use.mapper.ClassMapperImpl; +import org.tzi.use.mapper.InvariantMapperImpl; import org.tzi.use.mapper.ModelMapper; import org.tzi.use.repository.ClassRepo; import org.tzi.use.repository.ModelRepo; @@ -27,6 +28,7 @@ public class ModelService { private final ClassRepo classRepo; private final ModelMapper modelMapper; private final ClassMapperImpl classMapperImpl; + private final InvariantMapperImpl invariantMapperImpl; /** @@ -100,8 +102,10 @@ public List getModelAssociations() { return null; } - public List getModelInvariants () { - // implement later - return null; + public List getModelInvariants (String modelName) { + Optional modelOpt = modelRepo.findById(modelName); + return modelOpt.get().getInvariants().stream() + .map(invariantMapperImpl::toDTO) + .toList(); } } From 7af5fa2db40b5896632f1074b699f06b4fbec12d Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 16 Oct 2025 20:18:56 +0200 Subject: [PATCH 077/148] Not deprecated --- .../main/java/org/tzi/use/rest/controller/ModelController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 592eba5b4..0ea6e333c 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -280,9 +280,7 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { } - @Deprecated /** - * Deprecated for now * Placeholder method to retrieve all associations in a model */ @GetMapping("/model/{name}/associations") From cf43a0c81abaefafa120b192dff12bba16cacb70 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 16 Oct 2025 20:22:59 +0200 Subject: [PATCH 078/148] invariant endpoint --- .../use/rest/controller/ModelController.java | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 0ea6e333c..4e48c40a0 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -9,6 +9,7 @@ import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.tzi.use.DTO.ClassDTO; +import org.tzi.use.DTO.InvariantDTO; import org.tzi.use.DTO.ModelDTO; import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ModelService; @@ -290,12 +291,55 @@ public ResponseEntity getModelAssociations(@PathVariable String name) { } /** - * Placeholder method to retrieve all invariants in a model + * Retrieve all invariants in a model. + * @param modelName The name of the model. + * @return A collection of invariants with HATEOAS links. */ - @GetMapping("/model/{name}/invariants") - public ResponseEntity getModelInvariants(@PathVariable String modelName) { - // Implementation to be added - return null; + @GetMapping("/model/{modelName}/invariants") + public ResponseEntity>> getModelInvariants(@PathVariable String modelName) { + List invariants = modelService.getModelInvariants(modelName); + + List> invariantEntities = invariants.stream() + .map(invariant -> { + EntityModel entityModel = EntityModel.of(invariant); + + // Link to the parent model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelByName(modelName)) + .withRel("model")); + + // Self-link to this collection + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(modelName)) + .withSelfRel()); + + // Link to classes + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(modelName)) + .withRel("classes")); + + // Link to associations + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(modelName)) + .withRel("associations")); + + return entityModel; + }) + .collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(invariantEntities); + + // Self-link for the collection + collectionModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(modelName)) + .withSelfRel()); + + return new ResponseEntity<>(collectionModel, HttpStatus.OK); } /* From 2d3233a34461ab295793f5e7b0cb85ce1a206588 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 17 Oct 2025 01:31:07 +0200 Subject: [PATCH 079/148] post endpoint invariant --- .../main/java/org/tzi/use/UseModelFacade.java | 4 ++ .../use/rest/controller/ModelController.java | 39 +++++++++++++++++++ .../tzi/use/rest/services/ModelService.java | 16 +++++++- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 3d978bfff..d37adcab7 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -18,4 +18,8 @@ public static void createModel(String modelName) { public static void createClass(String className) throws UseApiException { useModelApi.createClass(className, false); } + + public static void createInvariant(InvariantDTO invariantDTOreq, String className) throws UseApiException { + useModelApi.createInvariant(invariantDTOreq.getInvName(),className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); + } } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 4e48c40a0..f1e567b9e 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -342,6 +342,45 @@ public ResponseEntity>> getModelInvari return new ResponseEntity<>(collectionModel, HttpStatus.OK); } + @PostMapping("/model/{modelName}/{className}/invariant") + public ResponseEntity> createInvariant(@PathVariable String modelName,@PathVariable String className, @RequestBody InvariantDTO invariantDTO) throws UseApiException { + InvariantDTO createdInvariant = modelService.createInvariant(modelName, invariantDTO, className); + + // Wrap the created invariant in an EntityModel for HATEOAS + EntityModel entityModel = EntityModel.of(createdInvariant); + + // Link to the parent model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelByName(modelName)) + .withRel("model")); + + // Link to the invariants listing for this model (also used as self since there's no single-invariant GET) + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelInvariants(modelName)) + .withSelfRel()); + + // Link to create another invariant in this model + entityModel.add(WebMvcLinkBuilder.linkTo(ModelController.class) + .slash("model").slash(modelName).slash("invariant") + .withRel("create-invariant")); + + // Link to classes for this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelClasses(modelName)) + .withRel("classes")); + + // Link to associations for this model + entityModel.add(WebMvcLinkBuilder.linkTo( + WebMvcLinkBuilder.methodOn(ModelController.class) + .getModelAssociations(modelName)) + .withRel("associations")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + /* Endpoints that are needed (prefix /api): POST /model - Create a new model :check: diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index bbae1f3e9..5a79a2ed3 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -10,6 +10,7 @@ import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; import org.tzi.use.entities.ClassNTT; +import org.tzi.use.entities.InvariantNTT; import org.tzi.use.entities.ModelNTT; import org.tzi.use.mapper.ClassMapperImpl; import org.tzi.use.mapper.InvariantMapperImpl; @@ -60,8 +61,9 @@ public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseAp Optional modelOfClass = modelRepo.findById(modelName); //check for modelOfClass presence is nessary? -> I think no because cannot create model via api if it doesn't exist - modelOfClass.get().addClass(tmp_classntt); + // if the class has attributed and operations this would not be enough UseModelFacade.createClass(tmp_classntt.getName()); + modelOfClass.get().addClass(tmp_classntt); modelRepo.save(modelOfClass.get()); classRepo.save(tmp_classntt); @@ -108,4 +110,16 @@ public List getModelInvariants (String modelName) { .map(invariantMapperImpl::toDTO) .toList(); } + + public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOreq, String className) throws UseApiException { + InvariantNTT tmp_invariantntt = invariantMapperImpl.toEntity(invariantDTOreq); + + Optional modelOfInvariant = modelRepo.findById(modelName); + + UseModelFacade.createInvariant(invariantDTOreq, className); + modelOfInvariant.get().getInvariants().add(tmp_invariantntt); + //TODO + modelRepo.save(modelOfInvariant.get()); + return invariantMapperImpl.toDTO(tmp_invariantntt); + } } From 92cd984a10e19f90c837d75a07bdc3b4f2f2c929 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 17 Oct 2025 01:34:16 +0200 Subject: [PATCH 080/148] deprecated unit tests need to be removed soon --- use-api/src/test/java/org/tzi/use/RestApiControllerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java b/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java index eb936a268..1d11e9b5b 100644 --- a/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java +++ b/use-api/src/test/java/org/tzi/use/RestApiControllerTest.java @@ -8,6 +8,7 @@ import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; +@Deprecated public class RestApiControllerTest { // // @BeforeAll From 5e187d937aff5d19704aabe64c71ab7928a9a0f6 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 31 Oct 2025 16:54:25 +0100 Subject: [PATCH 081/148] invariant can be added, but need the operation endpoint before that --- use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java | 4 ++-- use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java | 4 ---- use-api/src/main/java/org/tzi/use/UseModelFacade.java | 4 +++- .../src/main/java/org/tzi/use/rest/services/ModelService.java | 3 ++- 4 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java index aabd12ab3..e5564884e 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java @@ -18,8 +18,8 @@ public class AssociationDTO { private String name; - @Valid - private List associationEnds; +// @Valid +// private List associationEnds; private List roleNames; private Set associatedClassNames; diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java deleted file mode 100644 index 9b3bbc916..000000000 --- a/use-api/src/main/java/org/tzi/use/DTO/AssociationEndDTO.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.tzi.use.DTO; - -public class AssociationEndDTO { -} diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index d37adcab7..8f699165f 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -19,7 +19,9 @@ public static void createClass(String className) throws UseApiException { useModelApi.createClass(className, false); } - public static void createInvariant(InvariantDTO invariantDTOreq, String className) throws UseApiException { + public static void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { + createModel(modelName); + createClass(className); useModelApi.createInvariant(invariantDTOreq.getInvName(),className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 5a79a2ed3..0f581225b 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -115,8 +115,9 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr InvariantNTT tmp_invariantntt = invariantMapperImpl.toEntity(invariantDTOreq); Optional modelOfInvariant = modelRepo.findById(modelName); + // find the class inside the model by className - UseModelFacade.createInvariant(invariantDTOreq, className); + UseModelFacade.createInvariant(invariantDTOreq, className, modelName); modelOfInvariant.get().getInvariants().add(tmp_invariantntt); //TODO modelRepo.save(modelOfInvariant.get()); From 0611f39f497e9ec9c881c9e1a3d178e2fc01fd26 Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 2 Nov 2025 15:25:24 +0100 Subject: [PATCH 082/148] Update AssociationDTO.java --- .../java/org/tzi/use/DTO/AssociationDTO.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java index e5564884e..552ad8084 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java @@ -11,16 +11,29 @@ import java.util.Set; @Data -@Builder @NoArgsConstructor @AllArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) public class AssociationDTO { - private String name; - -// @Valid -// private List associationEnds; + private String name; private List roleNames; private Set associatedClassNames; } + + +enum AggregationKind { + NONE("association"), + AGGREGATION("aggregation"), + COMPOSITION("composition"); + + private final String displayName; + + AggregationKind(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + +} \ No newline at end of file From 1c1abf02e8cc7b70224851b5b92187dae6ed2038 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 08:47:50 +0000 Subject: [PATCH 083/148] Initial plan From 2d990c98ad625d6f62d10b993ad7df38968e9507 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 08:53:19 +0000 Subject: [PATCH 084/148] Add comprehensive Postman test collection for USE Web API Co-authored-by: husakki <81704101+husakki@users.noreply.github.com> --- ...se-webapi-extended.postman_collection.json | 1200 +++++++++++++++++ 1 file changed, 1200 insertions(+) create mode 100644 use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json diff --git a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json new file mode 100644 index 000000000..943e28c60 --- /dev/null +++ b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json @@ -0,0 +1,1200 @@ +{ + "info": { + "_postman_id": "e8a9f2d1-4f5c-4b2e-9a1c-3d5e6f7a8b9c", + "name": "use-webapi-extended", + "description": "Extended test collection for USE Web API with comprehensive test cases for models, classes, invariants, and associations", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", + "_exporter_id": "38619616" + }, + "item": [ + { + "name": "Model Tests", + "item": [ + { + "name": "Create Model - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response contains model data\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('name');", + " pm.expect(responseJson.name).to.equal('TestModel');", + "});", + "", + "pm.test(\"Response contains HATEOAS links\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"TestModel\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model" + }, + "response": [] + }, + { + "name": "Create Model - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400 or 500\", function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model" + }, + "response": [] + }, + { + "name": "Get Model by Name - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response contains model data\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('name');", + "});", + "", + "pm.test(\"Response contains HATEOAS links\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + " pm.expect(responseJson._links).to.have.property('self');", + " pm.expect(responseJson._links).to.have.property('classes');", + " pm.expect(responseJson._links).to.have.property('invariants');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/TestModel" + }, + "response": [] + }, + { + "name": "Get Model by Name - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404 or 500\", function () {", + " pm.expect([404, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/NonExistentModel" + }, + "response": [] + }, + { + "name": "Get All Models", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response contains models collection\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('_embedded');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/models" + }, + "response": [] + } + ] + }, + { + "name": "Class Tests", + "item": [ + { + "name": "Create Class in Model - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response contains class data\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('name_mclass');", + " pm.expect(responseJson.name_mclass).to.equal('Person');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"Person\",\n \"attributes\": [\n {\n \"name_attr\": \"name\",\n \"type\": \"String\"\n },\n {\n \"name_attr\": \"age\",\n \"type\": \"Integer\"\n }\n ],\n \"operations\": [\n {\n \"head\": \"getFullInfo()\",\n \"body\": null\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Class - Multiple Attributes Different Types", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response contains all attributes\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.attributes).to.be.an('array');", + " pm.expect(responseJson.attributes).to.have.lengthOf(5);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"Employee\",\n \"attributes\": [\n {\n \"name_attr\": \"id\",\n \"type\": \"Integer\"\n },\n {\n \"name_attr\": \"firstName\",\n \"type\": \"String\"\n },\n {\n \"name_attr\": \"lastName\",\n \"type\": \"String\"\n },\n {\n \"name_attr\": \"salary\",\n \"type\": \"Real\"\n },\n {\n \"name_attr\": \"isActive\",\n \"type\": \"Boolean\"\n }\n ],\n \"operations\": []\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Class - Multiple Operations", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response contains all operations\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.operations).to.be.an('array');", + " pm.expect(responseJson.operations).to.have.lengthOf(3);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"Calculator\",\n \"attributes\": [],\n \"operations\": [\n {\n \"head\": \"add(a:Integer, b:Integer):Integer\",\n \"body\": null\n },\n {\n \"head\": \"subtract(a:Integer, b:Integer):Integer\",\n \"body\": null\n },\n {\n \"head\": \"multiply(a:Integer, b:Integer):Integer\",\n \"body\": null\n }\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Get Model Classes - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response contains classes collection\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('_embedded');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/TestModel/classes" + }, + "response": [] + }, + { + "name": "Create Class - Invalid Attribute Type", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400 or 500\", function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"InvalidClass\",\n \"attributes\": [\n {\n \"name_attr\": \"field\",\n \"type\": \"InvalidType\"\n }\n ],\n \"operations\": []\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Class - Null Attributes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201 or handles null gracefully\", function () {", + " pm.expect([201, 400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"NullAttributesClass\",\n \"attributes\": null,\n \"operations\": null\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + } + ] + }, + { + "name": "Invariant Tests", + "item": [ + { + "name": "Create Invariant - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response contains invariant data\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('invName');", + " pm.expect(responseJson).to.have.property('invBody');", + "});", + "", + "pm.test(\"Response contains HATEOAS links\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"PositiveAge\",\n \"invBody\": \"self.age > 0\",\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Person/invariant" + }, + "response": [] + }, + { + "name": "Create Invariant - Existential", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Invariant is existential\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.isExistential).to.be.true;", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"HasEmployees\",\n \"invBody\": \"Employee.allInstances()->notEmpty()\",\n \"isExistential\": true\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Employee/invariant" + }, + "response": [] + }, + { + "name": "Create Invariant - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400 or 500\", function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"\",\n \"invBody\": \"self.age > 0\",\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Person/invariant" + }, + "response": [] + }, + { + "name": "Create Invariant - Empty Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400 or 500\", function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"EmptyBodyInv\",\n \"invBody\": \"\",\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Person/invariant" + }, + "response": [] + }, + { + "name": "Get Model Invariants - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response contains invariants collection\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.be.an('object');", + " pm.expect(responseJson).to.have.property('_embedded');", + "});", + "", + "pm.test(\"Response contains HATEOAS links\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + " pm.expect(responseJson._links).to.have.property('self');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/TestModel/invariants" + }, + "response": [] + }, + { + "name": "Create Invariant - Complex Expression", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response contains complex invariant\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.invName).to.equal('ValidSalary');", + " pm.expect(responseJson.invBody).to.include('salary');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"ValidSalary\",\n \"invBody\": \"self.salary >= 0 and self.salary <= 1000000\",\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Employee/invariant" + }, + "response": [] + } + ] + }, + { + "name": "Edge Cases and Error Handling", + "item": [ + { + "name": "Create Model - Duplicate Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400, 409, or 500\", function () {", + " pm.expect([400, 409, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"TestModel\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model" + }, + "response": [] + }, + { + "name": "Create Class - Duplicate Class Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400, 409, or 500\", function () {", + " pm.expect([400, 409, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"Person\",\n \"attributes\": [],\n \"operations\": []\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Class - Special Characters in Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response code indicates success or validation error\", function () {", + " pm.expect([201, 400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"Class@#$%\",\n \"attributes\": [],\n \"operations\": []\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Class - Very Long Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Response code indicates success or validation error\", function () {", + " pm.expect([201, 400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"ThisIsAVeryLongClassNameThatExceedsNormalExpectationsAndMightCauseIssuesWithTheSystem\",\n \"attributes\": [],\n \"operations\": []\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Invariant - Non-existent Class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404 or 500\", function () {", + " pm.expect([404, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"SomeInvariant\",\n \"invBody\": \"self.field > 0\",\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/NonExistentClass/invariant" + }, + "response": [] + }, + { + "name": "Get Classes - Non-existent Model", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404 or 500\", function () {", + " pm.expect([404, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/NonExistentModel/classes" + }, + "response": [] + } + ] + }, + { + "name": "Performance Tests", + "item": [ + { + "name": "GET Models - Response Time", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response time is below 500ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(500);", + "});", + "", + "pm.test(\"Response time is below 1000ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(1000);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/models" + }, + "response": [] + }, + { + "name": "POST Model - Response Time", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "let iter = pm.info.iteration || 0;", + "let uniqueName = `PerfModel-${iter}-${Date.now()}`;", + "pm.environment.set(\"uniqueModelName\", uniqueName);" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response time is below 500ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(500);", + "});", + "", + "pm.test(\"Response time is below 1000ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(1000);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{uniqueModelName}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model" + }, + "response": [] + }, + { + "name": "POST Class with Large Payload - Response Time", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "let iter = pm.info.iteration || 0;", + "let uniqueName = `LargeClass-${iter}-${Date.now()}`;", + "pm.environment.set(\"uniqueClassName\", uniqueName);" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response time is below 1000ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(1000);", + "});", + "", + "pm.test(\"Response time is below 2000ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(2000);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"{{uniqueClassName}}\",\n \"attributes\": [\n {\"name_attr\": \"attr1\", \"type\": \"String\"},\n {\"name_attr\": \"attr2\", \"type\": \"String\"},\n {\"name_attr\": \"attr3\", \"type\": \"Integer\"},\n {\"name_attr\": \"attr4\", \"type\": \"Real\"},\n {\"name_attr\": \"attr5\", \"type\": \"Boolean\"},\n {\"name_attr\": \"attr6\", \"type\": \"String\"},\n {\"name_attr\": \"attr7\", \"type\": \"String\"},\n {\"name_attr\": \"attr8\", \"type\": \"Integer\"},\n {\"name_attr\": \"attr9\", \"type\": \"Real\"},\n {\"name_attr\": \"attr10\", \"type\": \"Boolean\"}\n ],\n \"operations\": [\n {\"head\": \"operation1()\", \"body\": null},\n {\"head\": \"operation2()\", \"body\": null},\n {\"head\": \"operation3()\", \"body\": null},\n {\"head\": \"operation4()\", \"body\": null},\n {\"head\": \"operation5()\", \"body\": null}\n ]\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "GET Model by Name - Response Time", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response time is below 300ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(300);", + "});", + "", + "pm.test(\"Response time is below 500ms\", function () {", + " pm.expect(pm.response.responseTime).to.be.below(500);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/TestModel" + }, + "response": [] + } + ] + }, + { + "name": "HATEOAS and Link Validation", + "item": [ + { + "name": "Verify Model Links Structure", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response has HATEOAS _links object\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + " pm.expect(responseJson._links).to.be.an('object');", + "});", + "", + "pm.test(\"Self link is present and valid\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson._links).to.have.property('self');", + " pm.expect(responseJson._links.self).to.have.property('href');", + "});", + "", + "pm.test(\"Related resource links are present\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson._links).to.have.property('classes');", + " pm.expect(responseJson._links).to.have.property('invariants');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/TestModel" + }, + "response": [] + }, + { + "name": "Verify Classes Collection Links", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response has HATEOAS structure\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + " pm.expect(responseJson).to.have.property('_embedded');", + "});", + "", + "pm.test(\"Self link is present\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson._links).to.have.property('self');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": "localhost:8080/api/model/TestModel/classes" + }, + "response": [] + }, + { + "name": "Verify Invariant Creation Links", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "", + "pm.test(\"Response has HATEOAS links\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson).to.have.property('_links');", + "});", + "", + "pm.test(\"Model link is present\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson._links).to.have.property('model');", + "});", + "", + "pm.test(\"Self link is present\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson._links).to.have.property('self');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"invName\": \"LinkTestInvariant\",\n \"invBody\": \"true\",\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Person/invariant" + }, + "response": [] + } + ] + }, + { + "name": "Data Validation Tests", + "item": [ + { + "name": "Create Class - Missing Request Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Model - Malformed JSON", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\"name\": \"TestModel\",", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model" + }, + "response": [] + }, + { + "name": "Create Class - Wrong Data Type for Attributes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400 or 500\", function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"name_mclass\": \"WrongTypeClass\",\n \"attributes\": \"not-an-array\",\n \"operations\": []\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/class" + }, + "response": [] + }, + { + "name": "Create Invariant - Missing Required Fields", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400 or 500\", function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"isExistential\": false\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": "localhost:8080/api/model/TestModel/Person/invariant" + }, + "response": [] + } + ] + } + ] +} From 2d184b2544c4190617f6bd1a4a55c7d80c6d6fbe Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 15:20:02 +0100 Subject: [PATCH 085/148] Add association DTO, entity, and mapper --- .../org/tzi/use/DTO/AggregationTypeDTO.java | 18 ++++++++++ .../java/org/tzi/use/DTO/AssociationDTO.java | 34 ++++++------------- .../main/java/org/tzi/use/DTO/ModelDTO.java | 4 +-- .../tzi/use/entities/AggregationTypeNTT.java | 18 ++++++++++ .../org/tzi/use/entities/AssociationNTT.java | 27 +++++++++++++++ .../java/org/tzi/use/entities/ModelNTT.java | 2 +- .../org/tzi/use/mapper/AssociationMapper.java | 13 +++++++ 7 files changed, 89 insertions(+), 27 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/DTO/AggregationTypeDTO.java create mode 100644 use-api/src/main/java/org/tzi/use/entities/AggregationTypeNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/mapper/AssociationMapper.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/AggregationTypeDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AggregationTypeDTO.java new file mode 100644 index 000000000..43f8e7a3f --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/DTO/AggregationTypeDTO.java @@ -0,0 +1,18 @@ +package org.tzi.use.DTO; + +public enum AggregationTypeDTO { + NONE("association"), + AGGREGATION("aggregation"), + COMPOSITION("composition"); + + private final String displayName; + + AggregationTypeDTO(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + +} diff --git a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java index 552ad8084..f6e96e901 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/AssociationDTO.java @@ -1,39 +1,25 @@ package org.tzi.use.DTO; -import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import jakarta.validation.Valid; -import java.util.List; -import java.util.Set; - @Data @NoArgsConstructor @AllArgsConstructor public class AssociationDTO { - private String name; - private List roleNames; - private Set associatedClassNames; -} - + private String associationName; -enum AggregationKind { - NONE("association"), - AGGREGATION("aggregation"), - COMPOSITION("composition"); + private String end1ClassName; + private String end1RoleName; + private String end1Multiplicity; + private AggregationTypeDTO end1Aggregation; - private final String displayName; - - AggregationKind(String displayName) { - this.displayName = displayName; - } + private String end2ClassName; + private String end2RoleName; + private String end2Multiplicity; + private AggregationTypeDTO end2Aggregation; +} - public String getDisplayName() { - return displayName; - } -} \ No newline at end of file diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index e64e56024..32c6318fb 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -12,8 +12,8 @@ public class ModelDTO { private String name; private List classes = new ArrayList<>(); - private List associations = new ArrayList<>(); - private List invariants = new ArrayList<>(); + private List associations = new ArrayList<>(); + private List invariants = new ArrayList<>(); public ModelDTO(String name) { this.name = name; diff --git a/use-api/src/main/java/org/tzi/use/entities/AggregationTypeNTT.java b/use-api/src/main/java/org/tzi/use/entities/AggregationTypeNTT.java new file mode 100644 index 000000000..283875f75 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/AggregationTypeNTT.java @@ -0,0 +1,18 @@ +package org.tzi.use.entities; + +public enum AggregationTypeNTT { + NONE("association"), + AGGREGATION("aggregation"), + COMPOSITION("composition"); + + private final String displayName; + + AggregationTypeNTT(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + +} diff --git a/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java b/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java new file mode 100644 index 000000000..511aaa651 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java @@ -0,0 +1,27 @@ +package org.tzi.use.entities; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document("association") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AssociationNTT { + @Id + private String associationName; + + private String end1ClassName; + private String end1RoleName; + private String end1Multiplicity; + private AggregationTypeNTT end1Aggregation; + + private String end2ClassName; + private String end2RoleName; + private String end2Multiplicity; + private AggregationTypeNTT end2Aggregation; +} + diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index fba86463f..6bb158d97 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -19,7 +19,7 @@ public class ModelNTT { @Id private String name; private List classes = new ArrayList<>(); -// private List associations = new ArrayList<>(); + private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); public ModelNTT(String name) { diff --git a/use-api/src/main/java/org/tzi/use/mapper/AssociationMapper.java b/use-api/src/main/java/org/tzi/use/mapper/AssociationMapper.java new file mode 100644 index 000000000..7dd6e922a --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/AssociationMapper.java @@ -0,0 +1,13 @@ +package org.tzi.use.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.AssociationDTO; +import org.tzi.use.entities.AssociationNTT; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface AssociationMapper { + AssociationDTO toDTO(AssociationNTT entity); + + AssociationNTT toEntity(AssociationDTO dto); +} From b309218a5b03b3fa25940a490ef44169879d3f3b Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 15:20:15 +0100 Subject: [PATCH 086/148] assoc get --- .../org/tzi/use/rest/controller/ModelController.java | 12 ++++++++++-- .../java/org/tzi/use/rest/services/ModelService.java | 12 +++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index f1e567b9e..00ad4b1b6 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -8,6 +8,7 @@ import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +import org.tzi.use.DTO.AssociationDTO; import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.InvariantDTO; import org.tzi.use.DTO.ModelDTO; @@ -285,8 +286,15 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { * Placeholder method to retrieve all associations in a model */ @GetMapping("/model/{name}/associations") - public ResponseEntity getModelAssociations(@PathVariable String name) { - // Implementation to be added + public ResponseEntity getModelAssociations(@PathVariable String modelName) { + List associations = modelService.getModelAssociations(modelName); + return null; + } + + @PutMapping("/model/{modelName}/association") + public ResponseEntity createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) { + modelService.createAssociation(modelName, association); + return null; } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 0f581225b..3ff2480ca 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -12,6 +12,7 @@ import org.tzi.use.entities.ClassNTT; import org.tzi.use.entities.InvariantNTT; import org.tzi.use.entities.ModelNTT; +import org.tzi.use.mapper.AssociationMapperImpl; import org.tzi.use.mapper.ClassMapperImpl; import org.tzi.use.mapper.InvariantMapperImpl; import org.tzi.use.mapper.ModelMapper; @@ -30,6 +31,7 @@ public class ModelService { private final ModelMapper modelMapper; private final ClassMapperImpl classMapperImpl; private final InvariantMapperImpl invariantMapperImpl; + private final AssociationMapperImpl associationMapperImpl; /** @@ -99,9 +101,9 @@ public List getModelClasses(String modelName){ .toList(); } - public List getModelAssociations() { - // implement later - return null; + public List getModelAssociations(String modelName) { + Optional modelOpt = modelRepo.findById(modelName); + return modelOpt.get().getAssociations().stream().map(associationMapperImpl::toDTO).toList(); } public List getModelInvariants (String modelName) { @@ -123,4 +125,8 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr modelRepo.save(modelOfInvariant.get()); return invariantMapperImpl.toDTO(tmp_invariantntt); } + + public void createAssociation(String modelName, AssociationDTO association) { + + } } From 321b055ee85d2cb04e5cb3612e417d19adc244ed Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 18:38:49 +0100 Subject: [PATCH 087/148] create assoc --- use-api/src/main/java/org/tzi/use/UseModelFacade.java | 8 ++++++++ .../org/tzi/use/rest/controller/ModelController.java | 6 +++--- .../java/org/tzi/use/rest/services/ModelService.java | 11 +++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 8f699165f..29c06fdf9 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -24,4 +24,12 @@ public static void createInvariant(InvariantDTO invariantDTOreq, String classNam createClass(className); useModelApi.createInvariant(invariantDTOreq.getInvName(),className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); } + + public static void createAssociation(AssociationDTO association, String modelName) throws UseApiException { + createModel(modelName); + createClass(association.getEnd1ClassName()); + createClass(association.getEnd2ClassName()); + useModelApi.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), + association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); + } } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 00ad4b1b6..d61a2e3ef 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -285,14 +285,14 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { /** * Placeholder method to retrieve all associations in a model */ - @GetMapping("/model/{name}/associations") + @GetMapping("/model/{modelName}/associations") public ResponseEntity getModelAssociations(@PathVariable String modelName) { List associations = modelService.getModelAssociations(modelName); return null; } - @PutMapping("/model/{modelName}/association") - public ResponseEntity createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) { + @PostMapping("/model/{modelName}/association") + public ResponseEntity createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) throws UseApiException { modelService.createAssociation(modelName, association); return null; diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 3ff2480ca..6b094b74d 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -9,6 +9,7 @@ import org.tzi.use.DTO.ModelDTO; import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; +import org.tzi.use.entities.AssociationNTT; import org.tzi.use.entities.ClassNTT; import org.tzi.use.entities.InvariantNTT; import org.tzi.use.entities.ModelNTT; @@ -119,6 +120,7 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr Optional modelOfInvariant = modelRepo.findById(modelName); // find the class inside the model by className + // wenn die facade ein error bekommt wird die zeile darunter ausgeführt? UseModelFacade.createInvariant(invariantDTOreq, className, modelName); modelOfInvariant.get().getInvariants().add(tmp_invariantntt); //TODO @@ -126,7 +128,12 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr return invariantMapperImpl.toDTO(tmp_invariantntt); } - public void createAssociation(String modelName, AssociationDTO association) { - + public AssociationDTO createAssociation(String modelName, AssociationDTO association) throws UseApiException { + AssociationNTT tmp_associationntt = associationMapperImpl.toEntity(association); + Optional modelOfAssociation = modelRepo.findById(modelName); + UseModelFacade.createAssociation(association, modelName); + modelOfAssociation.get().getAssociations().add(tmp_associationntt); + modelRepo.save(modelOfAssociation.get()); + return associationMapperImpl.toDTO(tmp_associationntt); } } From 4713e1dffbb77d4535e289a077d9c95b6f9b55ac Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 20:12:40 +0100 Subject: [PATCH 088/148] operations and attributes --- .../java/org/tzi/use/DTO/OperationDTO.java | 5 +++-- .../org/tzi/use/entities/AttributeNTT.java | Bin 0 -> 704 bytes .../org/tzi/use/entities/OperationNTT.java | 19 ++++++++++++++++++ .../org/tzi/use/mapper/AttributeMapper.java | 14 +++++++++++++ .../org/tzi/use/mapper/OperationMapper.java | 14 +++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/entities/OperationNTT.java create mode 100644 use-api/src/main/java/org/tzi/use/mapper/AttributeMapper.java create mode 100644 use-api/src/main/java/org/tzi/use/mapper/OperationMapper.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java index b6ca09af9..e7d59c0c2 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/OperationDTO.java @@ -9,7 +9,8 @@ @AllArgsConstructor public class OperationDTO { - private String name; - private String body; + private String operationName; + private String[][] parameter; + private String returnType; } diff --git a/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java b/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java new file mode 100644 index 0000000000000000000000000000000000000000..106ec1b4a14f16ceea5a9df9abd7377d0f47bff1 GIT binary patch literal 704 zcmb7?O-=$q5QX2`#5;6c>83Bh1|w@Wa)AL_(qU$tFg+L{TwVRD8Z(`u z-puDmr%DU0Syu{jdew%LSJFe ztXP+D^>8r^)2Sh+!wQPmgqH)!YKA%OPk({qW>ys3=1J{;dOlW~S`Gz@rbUJ8 PYLebT4QI+7PF=qM(KUL7 literal 0 HcmV?d00001 diff --git a/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java b/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java new file mode 100644 index 000000000..5de2960c7 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java @@ -0,0 +1,19 @@ +package org.tzi.use.entities; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document("operation") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class OperationNTT { + + private String operationName; + private String[][] parameter; + private String returnType; + +} + diff --git a/use-api/src/main/java/org/tzi/use/mapper/AttributeMapper.java b/use-api/src/main/java/org/tzi/use/mapper/AttributeMapper.java new file mode 100644 index 000000000..6fc5a3bbb --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/AttributeMapper.java @@ -0,0 +1,14 @@ +package org.tzi.use.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.AttributeDTO; +import org.tzi.use.entities.AttributeNTT; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface AttributeMapper { + AttributeDTO toDTO(AttributeNTT entity); + + AttributeNTT toEntity(AttributeDTO dto); +} + diff --git a/use-api/src/main/java/org/tzi/use/mapper/OperationMapper.java b/use-api/src/main/java/org/tzi/use/mapper/OperationMapper.java new file mode 100644 index 000000000..ba73ba378 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/mapper/OperationMapper.java @@ -0,0 +1,14 @@ +package org.tzi.use.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import org.tzi.use.DTO.OperationDTO; +import org.tzi.use.entities.OperationNTT; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface OperationMapper { + OperationDTO toDTO(OperationNTT entity); + + OperationNTT toEntity(OperationDTO dto); +} + From 4ad9d019136f0a5f80232e9d17f2cd3269baa376 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 20:15:23 +0100 Subject: [PATCH 089/148] something happend with unknown chars --- .../java/org/tzi/use/entities/AttributeNTT.java | Bin 704 -> 332 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java b/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java index 106ec1b4a14f16ceea5a9df9abd7377d0f47bff1..0606e06d5d16cc34c4beaa7a08aba736ded688ea 100644 GIT binary patch literal 332 zcmZ{eF>V7f3y#*8JG_J5rUj4h_45$@UEMOCij!_!^g*$QfO)d;7*4E=0ozz_Ta)suIW literal 704 zcmb7?O-=$q5QX2`#5;6c>83Bh1|w@Wa)AL_(qU$tFg+L{TwVRD8Z(`u z-puDmr%DU0Syu{jdew%LSJFe ztXP+D^>8r^)2Sh+!wQPmgqH)!YKA%OPk({qW>ys3=1J{;dOlW~S`Gz@rbUJ8 PYLebT4QI+7PF=qM(KUL7 From dc817a4b17f670030695c43762555a7163e6bf29 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 20:20:58 +0100 Subject: [PATCH 090/148] class with to be impl endpoints --- .../use/rest/controller/ClassController.java | 25 ++++++++++++++++--- .../tzi/use/rest/services/ClassService.java | 11 ++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 use-api/src/main/java/org/tzi/use/rest/services/ClassService.java diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index ce600ef2e..fbbf7adf2 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -1,8 +1,25 @@ package org.tzi.use.rest.controller; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.tzi.use.rest.services.ClassService; + +@RestController +@RequestMapping("/api") +@RequiredArgsConstructor public class ClassController { - /* - Endpoint that are needed prefix /api/model/{id} - class should only have for attribute and operation (and assoc) - */ + private final ClassService classService; + + @GetMapping("/class/{className}") + @GetMapping("/class/attributes") + @GetMapping("/class/operations") + @GetMapping("/class/preposts") + + @PostMapping("/class/{className}/attribute") + @PostMapping("/class/{className}/operation") + @PostMapping("/class/{className}/prepost") + } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java new file mode 100644 index 000000000..1d5303b66 --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -0,0 +1,11 @@ +package org.tzi.use.rest.services; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.tzi.use.repository.ClassRepo; + +@Service +@RequiredArgsConstructor +public class ClassService { + private final ClassRepo classRepo; +} From 6109699e076b7c1d78adc443d2c501309de47812 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 20:34:09 +0100 Subject: [PATCH 091/148] class endpoints --- .../use/rest/controller/ClassController.java | 120 +++++++++++++++++- .../tzi/use/rest/services/ClassService.java | 46 +++++++ 2 files changed, 161 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index fbbf7adf2..8879ddbe9 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -1,25 +1,135 @@ package org.tzi.use.rest.controller; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.tzi.use.DTO.AttributeDTO; +import org.tzi.use.DTO.ClassDTO; +import org.tzi.use.DTO.OperationDTO; +import org.tzi.use.DTO.PrePostConditionDTO; import org.tzi.use.rest.services.ClassService; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; @RestController -@RequestMapping("/api") +@RequestMapping("/api/models/{modelName}") @RequiredArgsConstructor public class ClassController { private final ClassService classService; @GetMapping("/class/{className}") - @GetMapping("/class/attributes") - @GetMapping("/class/operations") - @GetMapping("/class/preposts") + public ResponseEntity> getClassByName(@PathVariable String modelName, @PathVariable String className) { + ClassDTO classDTO = classService.getClassByName(className); + EntityModel entityModel = EntityModel.of(classDTO); + entityModel.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withSelfRel()); + entityModel.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withRel("attributes")); + entityModel.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withRel("operations")); + entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withRel("preposts")); + return ResponseEntity.ok(entityModel); + } + + @GetMapping("/class/{className}/attributes") + public ResponseEntity>> getAttributes(@PathVariable String modelName, @PathVariable String className) { + List attributes = classService.getAttributes(className); + List> attributeModels = attributes.stream() + .map(attr -> EntityModel.of(attr, + linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attr.getName())).withSelfRel())) + .collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(attributeModels); + collectionModel.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withSelfRel()); + return ResponseEntity.ok(collectionModel); + } + + @GetMapping("/class/{className}/attribute/{attributeName}") + public ResponseEntity> getAttributeByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String attributeName) { + // Assuming ClassService has a method to get a single attribute by name + AttributeDTO attribute = classService.getAttributeByName(className, attributeName); + EntityModel entityModel = EntityModel.of(attribute); + entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attributeName)).withSelfRel()); + return ResponseEntity.ok(entityModel); + } + + + @GetMapping("/class/{className}/operations") + public ResponseEntity>> getOperations(@PathVariable String modelName, @PathVariable String className) { + List operations = classService.getOperations(className); + List> operationModels = operations.stream() + .map(op -> EntityModel.of(op, + linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, op.getOperationName())).withSelfRel())) + .collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(operationModels); + collectionModel.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withSelfRel()); + return ResponseEntity.ok(collectionModel); + } + + @GetMapping("/class/{className}/operation/{operationName}") + public ResponseEntity> getOperationByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String operationName) { + // Assuming ClassService has a method to get a single operation by name + OperationDTO operation = classService.getOperationByName(className, operationName); + EntityModel entityModel = EntityModel.of(operation); + entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, operationName)).withSelfRel()); + return ResponseEntity.ok(entityModel); + } + + @GetMapping("/class/{className}/preposts") + public ResponseEntity>> getPrePostConditions(@PathVariable String modelName, @PathVariable String className) { + List conditions = classService.getPrePostConditions(className); + List> conditionModels = conditions.stream() + .map(cond -> EntityModel.of(cond, + linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, cond.getName())).withSelfRel())) + .collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(conditionModels); + collectionModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withSelfRel()); + return ResponseEntity.ok(collectionModel); + } + + @GetMapping("/class/{className}/prepost/{conditionName}") + public ResponseEntity> getPrePostConditionByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String conditionName) { + // Assuming ClassService has a method to get a single pre/post condition by name + PrePostConditionDTO condition = classService.getPrePostConditionByName(className, conditionName); + EntityModel entityModel = EntityModel.of(condition); + entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, conditionName)).withSelfRel()); + return ResponseEntity.ok(entityModel); + } + @PostMapping("/class/{className}/attribute") + public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) { + AttributeDTO newAttribute = classService.addAttribute(className, attributeDTO); + EntityModel entityModel = EntityModel.of(newAttribute); + entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, newAttribute.getName())).withSelfRel()); + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + @PostMapping("/class/{className}/operation") - @PostMapping("/class/{className}/prepost") + public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) { + OperationDTO newOperation = classService.addOperation(className, operationDTO); + EntityModel entityModel = EntityModel.of(newOperation); + entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, newOperation.getOperationName())).withSelfRel()); + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + @PostMapping("/class/{className}/prepost") + public ResponseEntity> addPrePostCondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) { + PrePostConditionDTO newCondition = classService.addPrePostCondition(className, prePostConditionDTO); + EntityModel entityModel = EntityModel.of(newCondition); + entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, newCondition.getName())).withSelfRel()); + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index 1d5303b66..6f275f025 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -2,10 +2,56 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.tzi.use.DTO.AttributeDTO; +import org.tzi.use.DTO.ClassDTO; +import org.tzi.use.DTO.OperationDTO; +import org.tzi.use.DTO.PrePostConditionDTO; import org.tzi.use.repository.ClassRepo; +import java.util.List; + @Service @RequiredArgsConstructor public class ClassService { private final ClassRepo classRepo; + + public ClassDTO getClassByName(String className) { + return null; + } + + public List getAttributes(String className) { + return null; + } + + public List getOperations(String className) { + return null; + } + + public List getPrePostConditions(String className) { + return null; + } + + public AttributeDTO addAttribute(String className, AttributeDTO attributeDTO) { + return null; + } + + public OperationDTO addOperation(String className, OperationDTO operationDTO) { + return null; + } + + public PrePostConditionDTO addPrePostCondition(String className, PrePostConditionDTO prePostCondition) { + return null; + } + + public PrePostConditionDTO getPrePostConditionByName(String className, String conditionName) { + return null; + } + + public OperationDTO getOperationByName(String className, String operationName) { + return null; + } + + public AttributeDTO getAttributeByName(String className, String attributeName) { + return null; + } } From 815e2df254701393fdb78c6343b688c24cd3d411 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 21:25:19 +0100 Subject: [PATCH 092/148] modelcontroller optimize with static imports --- .../use/rest/controller/ModelController.java | 298 +++++++++++------- .../tzi/use/rest/services/ModelService.java | 8 + 2 files changed, 184 insertions(+), 122 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index d61a2e3ef..c479adbfd 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -1,13 +1,11 @@ package org.tzi.use.rest.controller; import lombok.RequiredArgsConstructor; +import org.springframework.hateoas.CollectionModel; +import org.springframework.hateoas.EntityModel; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.springframework.hateoas.EntityModel; -import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; - import org.tzi.use.DTO.AssociationDTO; import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.InvariantDTO; @@ -18,6 +16,9 @@ import java.util.List; import java.util.stream.Collectors; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; + @RestController @RequestMapping("/api") @RequiredArgsConstructor @@ -30,11 +31,12 @@ public class ModelController { /** * Create a new model + * * @param modelDTO The model data to create * @return The created model with HATEOAS links */ @PostMapping("/model") - public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO){ + public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { ModelDTO createdModel = modelService.createModel(modelDTO); // Create an EntityModel (HATEOAS) with the response @@ -42,27 +44,27 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m // Add HATEOAS links // Link to self - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(createdModel.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(createdModel.getName())) .withSelfRel()); // Link to get all classes in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(createdModel.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(createdModel.getName())) .withRel("classes")); // Link to get all associations in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(createdModel.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(createdModel.getName())) .withRel("associations")); // Link to get all invariants in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(createdModel.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(createdModel.getName())) .withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); @@ -70,6 +72,7 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m /** * Retrieve a model by its ID + * * @param name The ID of the model to retrieve * @return The model with HATEOAS links */ @@ -82,34 +85,65 @@ public ResponseEntity> getModelByName(@PathVariable String // Add HATEOAS links // Link to self - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(name)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(name)) .withSelfRel()); // Link to get all classes in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(name)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(name)) .withRel("classes")); // Link to get all associations in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(name)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(name)) .withRel("associations")); // Link to get all invariants in this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(name)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(name)) .withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } + @GetMapping("/model/{modelName}/association/{associationName}") + public ResponseEntity> getModelAssociationByName(@PathVariable String modelName, @PathVariable String associationName) { + AssociationDTO association = modelService.getAssociationByName(modelName, associationName); + EntityModel entityModel = EntityModel.of(association); + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociationByName(modelName, associationName)) + .withSelfRel()); + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(modelName)) + .withRel("model")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); + } + + @GetMapping("/model/{modelName}/invariant/{invariantName}") + public ResponseEntity> getModelInvariantByName(@PathVariable String modelName, @PathVariable String invariantName) { + InvariantDTO invariant = modelService.getInvariantByName(modelName, invariantName); + EntityModel entityModel = EntityModel.of(invariant); + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariantByName(modelName, invariantName)) + .withSelfRel()); + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(modelName)) + .withRel("model")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); + } + /** * Retrieve all models + * * @return List of all models with HATEOAS links */ @GetMapping("/models") @@ -118,53 +152,53 @@ public ResponseEntity>> getAllModels() { // Convert each model to an EntityModel with links List> modelEntities = models.stream() - .map(model -> { - EntityModel entityModel = EntityModel.of(model); + .map(model -> { + EntityModel entityModel = EntityModel.of(model); // Add self link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(model.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(model.getName())) .withSelfRel()); // Add classes link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(model.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(model.getName())) .withRel("classes")); // Add associations link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(model.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(model.getName())) .withRel("associations")); // Add invariants link - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(model.getName())) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(model.getName())) .withRel("invariants")); - return entityModel; - }) - .collect(Collectors.toList()); + return entityModel; + }) + .collect(Collectors.toList()); // Create a CollectionModel (container of EntityModels) CollectionModel> collectionModel = - CollectionModel.of(modelEntities); + CollectionModel.of(modelEntities); // Add link to this collection - collectionModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getAllModels()) + collectionModel.add(linkTo( + methodOn(ModelController.class) + .getAllModels()) .withSelfRel()); // Add link to create a new model - collectionModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .createModel(null)) - .withRel("create-model")); + collectionModel.add(linkTo( + methodOn(ModelController.class) + .createModel(null)) + .withRel("create-model")); return new ResponseEntity<>(collectionModel, HttpStatus.OK); @@ -178,32 +212,32 @@ public ResponseEntity> createClass(@PathVariable String mo EntityModel entityModel = EntityModel.of(createdClass); // Link to the parent model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(modelName)) .withRel("model")); // Link to the classes listing for this model (also used as self since there's no single-class GET) - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(modelName)) .withSelfRel()); // Link to create another class in this model - entityModel.add(WebMvcLinkBuilder.linkTo(ModelController.class) + entityModel.add(linkTo(ModelController.class) .slash("model").slash(modelName).slash("class") .withRel("create-class")); // Link to associations for this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(modelName)) .withRel("associations")); // Link to invariants for this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(modelName)) .withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); @@ -222,37 +256,37 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { EntityModel entityModel = EntityModel.of(classDTO); // Link to the parent model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(modelName)) .withRel("model")); // Link to this classes collection (self) - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(modelName)) .withSelfRel()); // Link to create another class try { - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .createClass(modelName, null)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .createClass(modelName, null)) .withRel("create-class")); } catch (UseApiException e) { throw new RuntimeException(e); } // Link to associations - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(modelName)) .withRel("associations")); // Link to invariants - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(modelName)) .withRel("invariants")); return entityModel; @@ -263,16 +297,16 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { CollectionModel> collectionModel = CollectionModel.of(classEntities); // Add self-link to the collection - collectionModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(modelName)) + collectionModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(modelName)) .withSelfRel()); // Add link to create a new class try { - collectionModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .createClass(modelName, null)) + collectionModel.add(linkTo( + methodOn(ModelController.class) + .createClass(modelName, null)) .withRel("create-class")); } catch (UseApiException e) { throw new RuntimeException(e); @@ -286,20 +320,40 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { * Placeholder method to retrieve all associations in a model */ @GetMapping("/model/{modelName}/associations") - public ResponseEntity getModelAssociations(@PathVariable String modelName) { + public ResponseEntity>> getModelAssociations(@PathVariable String modelName) { List associations = modelService.getModelAssociations(modelName); - return null; + + List> associationEntities = associations.stream() + .map(association -> { + EntityModel entityModel = EntityModel.of(association); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, association.getAssociationName())).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + return entityModel; + }) + .collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(associationEntities); + + collectionModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withSelfRel()); + + return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @PostMapping("/model/{modelName}/association") - public ResponseEntity createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) throws UseApiException { - modelService.createAssociation(modelName, association); + public ResponseEntity> createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) throws UseApiException { + AssociationDTO createdAssociation = modelService.createAssociation(modelName, association); - return null; + EntityModel entityModel = EntityModel.of(createdAssociation); + + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, createdAssociation.getAssociationName())).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } /** * Retrieve all invariants in a model. + * * @param modelName The name of the model. * @return A collection of invariants with HATEOAS links. */ @@ -312,27 +366,27 @@ public ResponseEntity>> getModelInvari EntityModel entityModel = EntityModel.of(invariant); // Link to the parent model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(modelName)) .withRel("model")); // Self-link to this collection - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(modelName)) .withSelfRel()); // Link to classes - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(modelName)) .withRel("classes")); // Link to associations - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(modelName)) .withRel("associations")); return entityModel; @@ -342,48 +396,48 @@ public ResponseEntity>> getModelInvari CollectionModel> collectionModel = CollectionModel.of(invariantEntities); // Self-link for the collection - collectionModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(modelName)) + collectionModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(modelName)) .withSelfRel()); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @PostMapping("/model/{modelName}/{className}/invariant") - public ResponseEntity> createInvariant(@PathVariable String modelName,@PathVariable String className, @RequestBody InvariantDTO invariantDTO) throws UseApiException { + public ResponseEntity> createInvariant(@PathVariable String modelName, @PathVariable String className, @RequestBody InvariantDTO invariantDTO) throws UseApiException { InvariantDTO createdInvariant = modelService.createInvariant(modelName, invariantDTO, className); // Wrap the created invariant in an EntityModel for HATEOAS EntityModel entityModel = EntityModel.of(createdInvariant); // Link to the parent model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelByName(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelByName(modelName)) .withRel("model")); // Link to the invariants listing for this model (also used as self since there's no single-invariant GET) - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelInvariants(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelInvariants(modelName)) .withSelfRel()); // Link to create another invariant in this model - entityModel.add(WebMvcLinkBuilder.linkTo(ModelController.class) + entityModel.add(linkTo(ModelController.class) .slash("model").slash(modelName).slash("invariant") .withRel("create-invariant")); // Link to classes for this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelClasses(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelClasses(modelName)) .withRel("classes")); // Link to associations for this model - entityModel.add(WebMvcLinkBuilder.linkTo( - WebMvcLinkBuilder.methodOn(ModelController.class) - .getModelAssociations(modelName)) + entityModel.add(linkTo( + methodOn(ModelController.class) + .getModelAssociations(modelName)) .withRel("associations")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 6b094b74d..b8d77df8c 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -95,6 +95,14 @@ public List getAllModels() { return modelRepo.findAll().stream().map(modelMapper::toDTO).toList(); } + public AssociationDTO getAssociationByName(String modelName, String associationName) { + return null; + } + + public InvariantDTO getInvariantByName(String modelName, String invariantName) { + return null; + } + public List getModelClasses(String modelName){ Optional modelOpt = modelRepo.findById(modelName); return modelOpt.get().getClasses().stream() From 1eb8bf776e7e3f7ab889d207212fa89eeb7bb353 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 10 Nov 2025 21:25:39 +0100 Subject: [PATCH 093/148] format --- .../use/rest/controller/ModelController.java | 313 ++++++------------ 1 file changed, 93 insertions(+), 220 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index c479adbfd..03b334a5a 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -44,28 +44,16 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m // Add HATEOAS links // Link to self - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(createdModel.getName())) - .withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(createdModel.getName())).withSelfRel()); // Link to get all classes in this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(createdModel.getName())) - .withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(createdModel.getName())).withRel("classes")); // Link to get all associations in this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(createdModel.getName())) - .withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(createdModel.getName())).withRel("associations")); // Link to get all invariants in this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(createdModel.getName())) - .withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(createdModel.getName())).withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @@ -85,28 +73,16 @@ public ResponseEntity> getModelByName(@PathVariable String // Add HATEOAS links // Link to self - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(name)) - .withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(name)).withSelfRel()); // Link to get all classes in this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(name)) - .withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(name)).withRel("classes")); // Link to get all associations in this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(name)) - .withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(name)).withRel("associations")); // Link to get all invariants in this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(name)) - .withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(name)).withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } @@ -115,14 +91,8 @@ public ResponseEntity> getModelByName(@PathVariable String public ResponseEntity> getModelAssociationByName(@PathVariable String modelName, @PathVariable String associationName) { AssociationDTO association = modelService.getAssociationByName(modelName, associationName); EntityModel entityModel = EntityModel.of(association); - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociationByName(modelName, associationName)) - .withSelfRel()); - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(modelName)) - .withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, associationName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } @@ -130,14 +100,8 @@ public ResponseEntity> getModelAssociationByName(@Pa public ResponseEntity> getModelInvariantByName(@PathVariable String modelName, @PathVariable String invariantName) { InvariantDTO invariant = modelService.getInvariantByName(modelName, invariantName); EntityModel entityModel = EntityModel.of(invariant); - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariantByName(modelName, invariantName)) - .withSelfRel()); - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(modelName)) - .withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariantByName(modelName, invariantName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } @@ -151,54 +115,33 @@ public ResponseEntity>> getAllModels() { List models = modelService.getAllModels(); // Convert each model to an EntityModel with links - List> modelEntities = models.stream() - .map(model -> { - EntityModel entityModel = EntityModel.of(model); - - // Add self link - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(model.getName())) - .withSelfRel()); - - // Add classes link - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(model.getName())) - .withRel("classes")); - - // Add associations link - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(model.getName())) - .withRel("associations")); - - // Add invariants link - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(model.getName())) - .withRel("invariants")); - - - return entityModel; - }) - .collect(Collectors.toList()); + List> modelEntities = models.stream().map(model -> { + EntityModel entityModel = EntityModel.of(model); + + // Add self link + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(model.getName())).withSelfRel()); + + // Add classes link + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(model.getName())).withRel("classes")); + + // Add associations link + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(model.getName())).withRel("associations")); + + // Add invariants link + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(model.getName())).withRel("invariants")); + + + return entityModel; + }).collect(Collectors.toList()); // Create a CollectionModel (container of EntityModels) - CollectionModel> collectionModel = - CollectionModel.of(modelEntities); + CollectionModel> collectionModel = CollectionModel.of(modelEntities); // Add link to this collection - collectionModel.add(linkTo( - methodOn(ModelController.class) - .getAllModels()) - .withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getAllModels()).withSelfRel()); // Add link to create a new model - collectionModel.add(linkTo( - methodOn(ModelController.class) - .createModel(null)) - .withRel("create-model")); + collectionModel.add(linkTo(methodOn(ModelController.class).createModel(null)).withRel("create-model")); return new ResponseEntity<>(collectionModel, HttpStatus.OK); @@ -212,33 +155,19 @@ public ResponseEntity> createClass(@PathVariable String mo EntityModel entityModel = EntityModel.of(createdClass); // Link to the parent model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(modelName)) - .withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); // Link to the classes listing for this model (also used as self since there's no single-class GET) - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(modelName)) - .withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); // Link to create another class in this model - entityModel.add(linkTo(ModelController.class) - .slash("model").slash(modelName).slash("class") - .withRel("create-class")); + entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("class").withRel("create-class")); // Link to associations for this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(modelName)) - .withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); // Link to invariants for this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(modelName)) - .withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @@ -251,63 +180,40 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { List modelClasses = modelService.getModelClasses(modelName); // Convert each class to an EntityModel with links - List> classEntities = modelClasses.stream() - .map(classDTO -> { - EntityModel entityModel = EntityModel.of(classDTO); - - // Link to the parent model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(modelName)) - .withRel("model")); - - // Link to this classes collection (self) - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(modelName)) - .withSelfRel()); - - // Link to create another class - try { - entityModel.add(linkTo( - methodOn(ModelController.class) - .createClass(modelName, null)) - .withRel("create-class")); - } catch (UseApiException e) { - throw new RuntimeException(e); - } - - // Link to associations - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(modelName)) - .withRel("associations")); - - // Link to invariants - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(modelName)) - .withRel("invariants")); - - return entityModel; - }) - .collect(Collectors.toList()); + List> classEntities = modelClasses.stream().map(classDTO -> { + EntityModel entityModel = EntityModel.of(classDTO); + + // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + // Link to this classes collection (self) + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); + + // Link to create another class + try { + entityModel.add(linkTo(methodOn(ModelController.class).createClass(modelName, null)).withRel("create-class")); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + + // Link to associations + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + + // Link to invariants + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withRel("invariants")); + + return entityModel; + }).collect(Collectors.toList()); // Create a CollectionModel CollectionModel> collectionModel = CollectionModel.of(classEntities); // Add self-link to the collection - collectionModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(modelName)) - .withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); // Add link to create a new class try { - collectionModel.add(linkTo( - methodOn(ModelController.class) - .createClass(modelName, null)) - .withRel("create-class")); + collectionModel.add(linkTo(methodOn(ModelController.class).createClass(modelName, null)).withRel("create-class")); } catch (UseApiException e) { throw new RuntimeException(e); } @@ -323,14 +229,12 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { public ResponseEntity>> getModelAssociations(@PathVariable String modelName) { List associations = modelService.getModelAssociations(modelName); - List> associationEntities = associations.stream() - .map(association -> { - EntityModel entityModel = EntityModel.of(association); - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, association.getAssociationName())).withSelfRel()); - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - return entityModel; - }) - .collect(Collectors.toList()); + List> associationEntities = associations.stream().map(association -> { + EntityModel entityModel = EntityModel.of(association); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, association.getAssociationName())).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + return entityModel; + }).collect(Collectors.toList()); CollectionModel> collectionModel = CollectionModel.of(associationEntities); @@ -361,45 +265,28 @@ public ResponseEntity> createAssociation(@PathVariab public ResponseEntity>> getModelInvariants(@PathVariable String modelName) { List invariants = modelService.getModelInvariants(modelName); - List> invariantEntities = invariants.stream() - .map(invariant -> { - EntityModel entityModel = EntityModel.of(invariant); - - // Link to the parent model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(modelName)) - .withRel("model")); - - // Self-link to this collection - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(modelName)) - .withSelfRel()); - - // Link to classes - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(modelName)) - .withRel("classes")); - - // Link to associations - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(modelName)) - .withRel("associations")); - - return entityModel; - }) - .collect(Collectors.toList()); + List> invariantEntities = invariants.stream().map(invariant -> { + EntityModel entityModel = EntityModel.of(invariant); + + // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + // Self-link to this collection + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withSelfRel()); + + // Link to classes + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withRel("classes")); + + // Link to associations + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + + return entityModel; + }).collect(Collectors.toList()); CollectionModel> collectionModel = CollectionModel.of(invariantEntities); // Self-link for the collection - collectionModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(modelName)) - .withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withSelfRel()); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @@ -412,33 +299,19 @@ public ResponseEntity> createInvariant(@PathVariable S EntityModel entityModel = EntityModel.of(createdInvariant); // Link to the parent model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelByName(modelName)) - .withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); // Link to the invariants listing for this model (also used as self since there's no single-invariant GET) - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelInvariants(modelName)) - .withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withSelfRel()); // Link to create another invariant in this model - entityModel.add(linkTo(ModelController.class) - .slash("model").slash(modelName).slash("invariant") - .withRel("create-invariant")); + entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("invariant").withRel("create-invariant")); // Link to classes for this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelClasses(modelName)) - .withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withRel("classes")); // Link to associations for this model - entityModel.add(linkTo( - methodOn(ModelController.class) - .getModelAssociations(modelName)) - .withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } From cb1454cbcffed0f8af1348e0b6ea91c932bdff82 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 13 Nov 2025 13:56:50 +0100 Subject: [PATCH 094/148] class service and moving prepostcondition to model --- .../main/java/org/tzi/use/DTO/ClassDTO.java | 1 + .../java/org/tzi/use/entities/ClassNTT.java | 6 +- .../use/rest/controller/ClassController.java | 58 +++++++++---------- .../tzi/use/rest/services/ClassService.java | 35 +++++++---- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index e9d194f5f..c2c95b503 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -14,4 +14,5 @@ public class ClassDTO { private List attributes = new ArrayList<>(); private List operations = new ArrayList<>(); private List associations = new ArrayList<>(); +// private List prepostcondition = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java index 0bde58db1..394b131ac 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java @@ -19,7 +19,7 @@ public class ClassNTT { @Id private String name; - private List attributes = new ArrayList<>(); - private List operations = new ArrayList<>(); - private List associations = new ArrayList<>(); + private List attributes = new ArrayList<>(); + private List operations = new ArrayList<>(); + private List associations = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 8879ddbe9..076bd06f4 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -37,7 +37,7 @@ public ResponseEntity> getClassByName(@PathVariable String entityModel.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withSelfRel()); entityModel.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withRel("attributes")); entityModel.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withRel("operations")); - entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withRel("preposts")); +// entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withRel("preposts")); return ResponseEntity.ok(entityModel); } @@ -86,27 +86,27 @@ public ResponseEntity> getOperationByName(@PathVariabl return ResponseEntity.ok(entityModel); } - @GetMapping("/class/{className}/preposts") - public ResponseEntity>> getPrePostConditions(@PathVariable String modelName, @PathVariable String className) { - List conditions = classService.getPrePostConditions(className); - List> conditionModels = conditions.stream() - .map(cond -> EntityModel.of(cond, - linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, cond.getName())).withSelfRel())) - .collect(Collectors.toList()); - - CollectionModel> collectionModel = CollectionModel.of(conditionModels); - collectionModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withSelfRel()); - return ResponseEntity.ok(collectionModel); - } - - @GetMapping("/class/{className}/prepost/{conditionName}") - public ResponseEntity> getPrePostConditionByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String conditionName) { - // Assuming ClassService has a method to get a single pre/post condition by name - PrePostConditionDTO condition = classService.getPrePostConditionByName(className, conditionName); - EntityModel entityModel = EntityModel.of(condition); - entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, conditionName)).withSelfRel()); - return ResponseEntity.ok(entityModel); - } +// @GetMapping("/class/{className}/preposts") +// public ResponseEntity>> getPrePostConditions(@PathVariable String modelName, @PathVariable String className) { +// List conditions = classService.getPrePostConditions(className); +// List> conditionModels = conditions.stream() +// .map(cond -> EntityModel.of(cond, +// linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, cond.getName())).withSelfRel())) +// .collect(Collectors.toList()); +// +// CollectionModel> collectionModel = CollectionModel.of(conditionModels); +// collectionModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withSelfRel()); +// return ResponseEntity.ok(collectionModel); +// } + +// @GetMapping("/class/{className}/prepost/{conditionName}") +// public ResponseEntity> getPrePostConditionByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String conditionName) { +// // Assuming ClassService has a method to get a single pre/post condition by name +// PrePostConditionDTO condition = classService.getPrePostConditionByName(className, conditionName); +// EntityModel entityModel = EntityModel.of(condition); +// entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, conditionName)).withSelfRel()); +// return ResponseEntity.ok(entityModel); +// } @PostMapping("/class/{className}/attribute") @@ -125,11 +125,11 @@ public ResponseEntity> addOperation(@PathVariable Stri return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } - @PostMapping("/class/{className}/prepost") - public ResponseEntity> addPrePostCondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) { - PrePostConditionDTO newCondition = classService.addPrePostCondition(className, prePostConditionDTO); - EntityModel entityModel = EntityModel.of(newCondition); - entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, newCondition.getName())).withSelfRel()); - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); - } +// @PostMapping("/class/{className}/prepost") +// public ResponseEntity> addPrePostCondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) { +// PrePostConditionDTO newCondition = classService.addPrePostCondition(className, prePostConditionDTO); +// EntityModel entityModel = EntityModel.of(newCondition); +// entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, newCondition.getName())).withSelfRel()); +// return new ResponseEntity<>(entityModel, HttpStatus.CREATED); +// } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index 6f275f025..a8c266f1e 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -6,30 +6,41 @@ import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.OperationDTO; import org.tzi.use.DTO.PrePostConditionDTO; +import org.tzi.use.entities.ClassNTT; +import org.tzi.use.mapper.*; import org.tzi.use.repository.ClassRepo; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor public class ClassService { private final ClassRepo classRepo; + private final ClassMapper classMapper; + private final AttributeMapper attributeMapper; + private final OperationMapper operationMapper; + private final PrePostConditionMapper prePostConditionMapper; public ClassDTO getClassByName(String className) { - return null; + Optional classNTTOpt = classRepo.findById(className); + return classMapper.toDTO(classNTTOpt.get()); } public List getAttributes(String className) { - return null; + Optional classNTTOpt = classRepo.findById(className); + return classNTTOpt.get().getAttributes().stream().map(attributeMapper::toDTO).toList(); } public List getOperations(String className) { - return null; + Optional classNTTOpt = classRepo.findById(className); + return classNTTOpt.get().getOperations().stream().map(operationMapper::toDTO).toList(); } - public List getPrePostConditions(String className) { - return null; - } +// public List getPrePostConditions(String className) { +// Optional classNTTOpt = classRepo.findById(className); +// return classNTTOpt.get().getPrePostCond().stream().map(prePostConditionMapper::toDTO).toList(); +// } public AttributeDTO addAttribute(String className, AttributeDTO attributeDTO) { return null; @@ -39,13 +50,13 @@ public OperationDTO addOperation(String className, OperationDTO operationDTO) { return null; } - public PrePostConditionDTO addPrePostCondition(String className, PrePostConditionDTO prePostCondition) { - return null; - } +// public PrePostConditionDTO addPrePostCondition(String className, PrePostConditionDTO prePostCondition) { +// return null; +// } - public PrePostConditionDTO getPrePostConditionByName(String className, String conditionName) { - return null; - } +// public PrePostConditionDTO getPrePostConditionByName(String className, String conditionName) { +// return null; +// } public OperationDTO getOperationByName(String className, String operationName) { return null; From e00c0c6fbb9fa60cea5cb7742c4e57f5caac050d Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 13 Nov 2025 20:35:28 +0100 Subject: [PATCH 095/148] renaming --- .../java/org/tzi/use/rest/controller/ClassController.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 076bd06f4..1eced4ac3 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -12,11 +12,9 @@ import org.tzi.use.DTO.AttributeDTO; import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.OperationDTO; -import org.tzi.use.DTO.PrePostConditionDTO; import org.tzi.use.rest.services.ClassService; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import java.util.List; import java.util.stream.Collectors; @@ -111,7 +109,7 @@ public ResponseEntity> getOperationByName(@PathVariabl @PostMapping("/class/{className}/attribute") public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) { - AttributeDTO newAttribute = classService.addAttribute(className, attributeDTO); + AttributeDTO newAttribute = classService.createAttribute(className, attributeDTO); EntityModel entityModel = EntityModel.of(newAttribute); entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, newAttribute.getName())).withSelfRel()); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); @@ -119,7 +117,7 @@ public ResponseEntity> addAttribute(@PathVariable Stri @PostMapping("/class/{className}/operation") public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) { - OperationDTO newOperation = classService.addOperation(className, operationDTO); + OperationDTO newOperation = classService.createOperation(className, operationDTO); EntityModel entityModel = EntityModel.of(newOperation); entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, newOperation.getOperationName())).withSelfRel()); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); From ebbcfb209c46ca0a48f6473571566a20bf569092 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 13 Nov 2025 20:35:42 +0100 Subject: [PATCH 096/148] new repo method and todo --- use-api/src/main/java/org/tzi/use/repository/ModelRepo.java | 3 +++ .../src/main/java/org/tzi/use/rest/services/ModelService.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java b/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java index 9378d247e..0ded7ac3b 100644 --- a/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java +++ b/use-api/src/main/java/org/tzi/use/repository/ModelRepo.java @@ -3,5 +3,8 @@ import org.springframework.data.mongodb.repository.MongoRepository; import org.tzi.use.entities.ModelNTT; +import java.util.Optional; + public interface ModelRepo extends MongoRepository { + Optional findByClassesName(String className); } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index b8d77df8c..f50bda4ee 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -128,7 +128,7 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr Optional modelOfInvariant = modelRepo.findById(modelName); // find the class inside the model by className - // wenn die facade ein error bekommt wird die zeile darunter ausgeführt? + //TODO wenn die facade ein error bekommt wird die zeile darunter ausgeführt? UseModelFacade.createInvariant(invariantDTOreq, className, modelName); modelOfInvariant.get().getInvariants().add(tmp_invariantntt); //TODO From c6f6784f83ccea9417b94f702e95f2dba12fccec Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 13 Nov 2025 20:36:04 +0100 Subject: [PATCH 097/148] create operation and attribute --- .../main/java/org/tzi/use/UseModelFacade.java | 37 +++++++++++-- .../tzi/use/rest/services/ClassService.java | 53 ++++++++++++++----- 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 29c06fdf9..74fcdff77 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -3,9 +3,8 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.DTO.*; -import org.tzi.use.entities.ClassNTT; -import org.tzi.use.entities.ModelNTT; -import org.tzi.use.uml.mm.MInvalidModelException; +import org.tzi.use.entities.AttributeNTT; +import org.tzi.use.entities.OperationNTT; public class UseModelFacade { private static final UseModelApi useModelApi = new UseModelApi(); @@ -32,4 +31,36 @@ public static void createAssociation(AssociationDTO association, String modelNam useModelApi.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); } + + public static void createAttribute(String modelName, String className, AttributeNTT attributeNTT) { + createModel(modelName); + //TODO might change to methode signature with UseApiException + try { + createClass(className); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + try { + useModelApi.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + + } + + + public static void createOperation(String modelName, String className, OperationNTT operationNTT) { + createModel(modelName); + //TODO might change to methode signature with UseApiException + try { + createClass(className); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + try { + useModelApi.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); + } catch (UseApiException e) { + throw new RuntimeException(e); + } + } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index a8c266f1e..3b9de12af 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -5,36 +5,42 @@ import org.tzi.use.DTO.AttributeDTO; import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.OperationDTO; -import org.tzi.use.DTO.PrePostConditionDTO; +import org.tzi.use.UseModelFacade; +import org.tzi.use.entities.AttributeNTT; import org.tzi.use.entities.ClassNTT; +import org.tzi.use.entities.OperationNTT; import org.tzi.use.mapper.*; import org.tzi.use.repository.ClassRepo; +import org.tzi.use.repository.ModelRepo; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor public class ClassService { private final ClassRepo classRepo; + private final ModelRepo modelRepo; // added to resolve model by class name private final ClassMapper classMapper; private final AttributeMapper attributeMapper; private final OperationMapper operationMapper; private final PrePostConditionMapper prePostConditionMapper; public ClassDTO getClassByName(String className) { - Optional classNTTOpt = classRepo.findById(className); - return classMapper.toDTO(classNTTOpt.get()); + ClassNTT classNTT = classRepo.findById(className) + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); + return classMapper.toDTO(classNTT); } public List getAttributes(String className) { - Optional classNTTOpt = classRepo.findById(className); - return classNTTOpt.get().getAttributes().stream().map(attributeMapper::toDTO).toList(); + ClassNTT classNTT = classRepo.findById(className) + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); + return classNTT.getAttributes().stream().map(attributeMapper::toDTO).toList(); } public List getOperations(String className) { - Optional classNTTOpt = classRepo.findById(className); - return classNTTOpt.get().getOperations().stream().map(operationMapper::toDTO).toList(); + ClassNTT classNTT = classRepo.findById(className) + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); + return classNTT.getOperations().stream().map(operationMapper::toDTO).toList(); } // public List getPrePostConditions(String className) { @@ -42,12 +48,35 @@ public List getOperations(String className) { // return classNTTOpt.get().getPrePostCond().stream().map(prePostConditionMapper::toDTO).toList(); // } - public AttributeDTO addAttribute(String className, AttributeDTO attributeDTO) { - return null; + public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) { + AttributeNTT attributeNTT = attributeMapper.toEntity(attributeDTO); + ClassNTT classNTT = classRepo.findById(className) + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); + // Resolve model name that contains this class + String modelName = getModelNameForClass(className); + UseModelFacade.createAttribute(modelName, className, attributeNTT); + classNTT.getAttributes().add(attributeNTT); + classRepo.save(classNTT); + return attributeMapper.toDTO(attributeNTT); } - public OperationDTO addOperation(String className, OperationDTO operationDTO) { - return null; + private String getModelNameForClass(String className) { + return modelRepo.findByClassesName(className) + .map(m -> m.getName()) + .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); + } + + public OperationDTO createOperation(String className, OperationDTO operationDTO) { + OperationNTT operationNTT = operationMapper.toEntity(operationDTO); + ClassNTT classNTT = classRepo.findById(className) + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); + + String modelName = getModelNameForClass(className); + UseModelFacade.createOperation(modelName, className, operationNTT); + + classNTT.getOperations().add(operationNTT); + classRepo.save(classNTT); + return operationMapper.toDTO(operationNTT); } // public PrePostConditionDTO addPrePostCondition(String className, PrePostConditionDTO prePostCondition) { From 7cad87789682c5b954125511a017bf374e5a2235 Mon Sep 17 00:00:00 2001 From: husakki Date: Sat, 15 Nov 2025 15:22:54 +0100 Subject: [PATCH 098/148] UseModelFacade overhaul with cached models Updated UseModelFacade to cache UseModelApi instances per model name, ensuring model state is maintained across operations. --- .../main/java/org/tzi/use/UseModelFacade.java | 114 ++++++++++++------ .../use/rest/controller/ClassController.java | 5 +- .../tzi/use/rest/services/ClassService.java | 5 +- .../tzi/use/rest/services/ModelService.java | 6 +- 4 files changed, 87 insertions(+), 43 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 74fcdff77..8c87e71ed 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -5,62 +5,102 @@ import org.tzi.use.DTO.*; import org.tzi.use.entities.AttributeNTT; import org.tzi.use.entities.OperationNTT; +import org.tzi.use.uml.mm.MClass; + +import java.util.HashMap; +import java.util.Map; public class UseModelFacade { - private static final UseModelApi useModelApi = new UseModelApi(); + // Cache UseModelApi instances per model name to maintain state + private static final Map modelApiCache = new HashMap<>(); + + /** + * Gets or creates a UseModelApi instance for the given model name. + * This ensures we maintain the same model instance across multiple operations. + */ + private static UseModelApi getOrCreateModelApi(String modelName) { + return modelApiCache.computeIfAbsent(modelName, name -> { + UseModelApi api = new UseModelApi(); + api.createModel(name); + return api; + }); + } public static void createModel(String modelName) { - useModelApi.createModel(modelName); + // Use getOrCreateModelApi to ensure idempotent behavior + getOrCreateModelApi(modelName); } + /** + * Creates a class in the specified model if it doesn't already exist. + * This is idempotent - calling it multiple times with the same parameters is safe. + * + * @param modelName The name of the model containing the class + * @param className The name of the class to create + * @throws UseApiException If there's an error creating the class + */ + public static void createClass(String modelName, String className) throws UseApiException { + UseModelApi api = getOrCreateModelApi(modelName); - public static void createClass(String className) throws UseApiException { - useModelApi.createClass(className, false); + // Check if class already exists + MClass existingClass = api.getClass(className); + if (existingClass == null) { + api.createClass(className, false); + } + // If class already exists, do nothing (idempotent) } public static void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { - createModel(modelName); - createClass(className); - useModelApi.createInvariant(invariantDTOreq.getInvName(),className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); + UseModelApi api = getOrCreateModelApi(modelName); + createClass(modelName, className); + api.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); } public static void createAssociation(AssociationDTO association, String modelName) throws UseApiException { - createModel(modelName); - createClass(association.getEnd1ClassName()); - createClass(association.getEnd2ClassName()); - useModelApi.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), + UseModelApi api = getOrCreateModelApi(modelName); + createClass(modelName, association.getEnd1ClassName()); + createClass(modelName, association.getEnd2ClassName()); + api.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); } - public static void createAttribute(String modelName, String className, AttributeNTT attributeNTT) { - createModel(modelName); - //TODO might change to methode signature with UseApiException - try { - createClass(className); - } catch (UseApiException e) { - throw new RuntimeException(e); - } - try { - useModelApi.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); - } catch (UseApiException e) { - throw new RuntimeException(e); - } + public static void createAttribute(String modelName, String className, AttributeNTT attributeNTT) throws UseApiException { + UseModelApi api = getOrCreateModelApi(modelName); + createClass(modelName, className); + api.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); + } + + public static void createOperation(String modelName, String className, OperationNTT operationNTT) throws UseApiException { + UseModelApi api = getOrCreateModelApi(modelName); + createClass(modelName, className); + api.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); } + /** + * Clears the cached model for the given model name. + * This is useful when you want to start fresh with a model. + * @param modelName The name of the model to clear + */ + public static void clearModel(String modelName) { + modelApiCache.remove(modelName); + } - public static void createOperation(String modelName, String className, OperationNTT operationNTT) { - createModel(modelName); - //TODO might change to methode signature with UseApiException - try { - createClass(className); - } catch (UseApiException e) { - throw new RuntimeException(e); - } - try { - useModelApi.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); - } catch (UseApiException e) { - throw new RuntimeException(e); - } + /** + * Clears all cached models. + * This is useful for testing or when you want to reset the entire state. + */ + public static void clearAllModels() { + modelApiCache.clear(); + } + + /** + * Gets the UseModelApi instance for a specific model name. + * Returns null if the model hasn't been created yet. + * @param modelName The name of the model + * @return The UseModelApi instance or null if not found + */ + public static UseModelApi getModelApi(String modelName) { + return modelApiCache.get(modelName); } } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 1eced4ac3..aa4e3faff 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -12,6 +12,7 @@ import org.tzi.use.DTO.AttributeDTO; import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.OperationDTO; +import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ClassService; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.CollectionModel; @@ -108,7 +109,7 @@ public ResponseEntity> getOperationByName(@PathVariabl @PostMapping("/class/{className}/attribute") - public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) { + public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) throws UseApiException { AttributeDTO newAttribute = classService.createAttribute(className, attributeDTO); EntityModel entityModel = EntityModel.of(newAttribute); entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, newAttribute.getName())).withSelfRel()); @@ -116,7 +117,7 @@ public ResponseEntity> addAttribute(@PathVariable Stri } @PostMapping("/class/{className}/operation") - public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) { + public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) throws UseApiException { OperationDTO newOperation = classService.createOperation(className, operationDTO); EntityModel entityModel = EntityModel.of(newOperation); entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, newOperation.getOperationName())).withSelfRel()); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index 3b9de12af..b2bdffb66 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -6,6 +6,7 @@ import org.tzi.use.DTO.ClassDTO; import org.tzi.use.DTO.OperationDTO; import org.tzi.use.UseModelFacade; +import org.tzi.use.api.UseApiException; import org.tzi.use.entities.AttributeNTT; import org.tzi.use.entities.ClassNTT; import org.tzi.use.entities.OperationNTT; @@ -48,7 +49,7 @@ public List getOperations(String className) { // return classNTTOpt.get().getPrePostCond().stream().map(prePostConditionMapper::toDTO).toList(); // } - public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) { + public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) throws UseApiException { AttributeNTT attributeNTT = attributeMapper.toEntity(attributeDTO); ClassNTT classNTT = classRepo.findById(className) .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); @@ -66,7 +67,7 @@ private String getModelNameForClass(String className) { .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); } - public OperationDTO createOperation(String className, OperationDTO operationDTO) { + public OperationDTO createOperation(String className, OperationDTO operationDTO) throws UseApiException { OperationNTT operationNTT = operationMapper.toEntity(operationDTO); ClassNTT classNTT = classRepo.findById(className) .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index f50bda4ee..81692fc6d 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -64,8 +64,10 @@ public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseAp Optional modelOfClass = modelRepo.findById(modelName); //check for modelOfClass presence is nessary? -> I think no because cannot create model via api if it doesn't exist - // if the class has attributed and operations this would not be enough - UseModelFacade.createClass(tmp_classntt.getName()); +// // if the class has attributed and operations this would not be enough +// UseModelFacade.createClass(tmp_classntt.getName()); + // Create the class in the USE model (now with proper model context) + UseModelFacade.createClass(modelName, tmp_classntt.getName()); modelOfClass.get().addClass(tmp_classntt); modelRepo.save(modelOfClass.get()); From e79e8f50335bbddb6833fa7a311fa1c78e9e274b Mon Sep 17 00:00:00 2001 From: husakki Date: Sun, 23 Nov 2025 19:55:45 +0100 Subject: [PATCH 099/148] found invariant error the problem was the error message from the use-core module this said "Undefined operation named..." but its actually the attribute that wasnt present, so for testing i just did it like this and it works --- .../main/java/org/tzi/use/UseModelFacade.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 8c87e71ed..3853edc93 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -53,7 +53,30 @@ public static void createClass(String modelName, String className) throws UseApi public static void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { UseModelApi api = getOrCreateModelApi(modelName); createClass(modelName, className); + +// createOperation(modelName, className, new OperationNTT("calculateAge", new String[][]{}, "Boolean")); + // Create a query operation WITH a body + api.createAttribute(className, "birthYear", "Integer"); + api.createAttribute(className, "calculateAge", "Integer"); +// api.createQueryOperation( +// className, +// "calculateAge", +// new String[][]{}, // no parameters +// "Integer", // return type (should be Integer, not Boolean) +// "(2024 - self.birthYear)", // the actual implementation +// false // not a constructor +// ); +// // The invariant body from the request is "self.calculateAge >= 18" +// String originalInvBody = invariantDTOreq.getInvBody(); +// +// // The definition of the 'calculateAge' operation +// String calculateAgeBody = "(2024 - self.birthYear)"; +// +// // Replace the call to 'calculateAge' in the invariant with its actual OCL expression +// String expandedInvBody = originalInvBody.replace("self.calculateAge", calculateAgeBody); + api.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); + } public static void createAssociation(AssociationDTO association, String modelName) throws UseApiException { From aa30de670dfa570b4d7f4d78b50ae61778f35daa Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 27 Nov 2025 00:11:25 +0100 Subject: [PATCH 100/148] prepostcondition endpoints --- .../main/java/org/tzi/use/DTO/ModelDTO.java | 4 ++ .../main/java/org/tzi/use/UseModelFacade.java | 9 ++- .../java/org/tzi/use/entities/ModelNTT.java | 5 ++ .../use/rest/controller/ModelController.java | 70 +++++++++++++++++-- .../tzi/use/rest/services/ModelService.java | 41 +++++++---- 5 files changed, 112 insertions(+), 17 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index 32c6318fb..f70a328ae 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -2,9 +2,12 @@ import lombok.*; import org.tzi.use.entities.InvariantNTT; +import org.tzi.use.entities.PrePostConditionNTT; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; @Data @AllArgsConstructor @@ -14,6 +17,7 @@ public class ModelDTO { private List classes = new ArrayList<>(); private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); + private Map prePostConditions = new TreeMap<>(); public ModelDTO(String name) { this.name = name; diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 3853edc93..fa3ff2d11 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -5,6 +5,7 @@ import org.tzi.use.DTO.*; import org.tzi.use.entities.AttributeNTT; import org.tzi.use.entities.OperationNTT; +import org.tzi.use.entities.PrePostConditionNTT; import org.tzi.use.uml.mm.MClass; import java.util.HashMap; @@ -57,7 +58,7 @@ public static void createInvariant(InvariantDTO invariantDTOreq, String classNam // createOperation(modelName, className, new OperationNTT("calculateAge", new String[][]{}, "Boolean")); // Create a query operation WITH a body api.createAttribute(className, "birthYear", "Integer"); - api.createAttribute(className, "calculateAge", "Integer"); +// api.createAttribute(className, "calculateAge", "Integer"); // api.createQueryOperation( // className, // "calculateAge", @@ -126,4 +127,10 @@ public static void clearAllModels() { public static UseModelApi getModelApi(String modelName) { return modelApiCache.get(modelName); } + + public static void createPrePostCondition(PrePostConditionNTT ppc, String className, String modelName) throws UseApiException { + UseModelApi api = getOrCreateModelApi(modelName); + createClass(modelName, className); + api.createPrePostCondition(className,ppc.getOperationName(),ppc.getName(), ppc.getCondition(), ppc.isPre()); + } } diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index 6bb158d97..be4fbd087 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -9,6 +9,8 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; @Document("model") @Data @@ -19,8 +21,11 @@ public class ModelNTT { @Id private String name; private List classes = new ArrayList<>(); + // String treemap private List associations = new ArrayList<>(); + // String treemap private List invariants = new ArrayList<>(); + private Map prePostConditions = new TreeMap<>(); public ModelNTT(String name) { this.name = name; diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 03b334a5a..7030abceb 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -6,10 +6,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.tzi.use.DTO.AssociationDTO; -import org.tzi.use.DTO.ClassDTO; -import org.tzi.use.DTO.InvariantDTO; -import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.DTO.*; import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ModelService; @@ -316,6 +313,71 @@ public ResponseEntity> createInvariant(@PathVariable S return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } + @PostMapping("/model/{modelName}/{className}/prepostcondition") + public ResponseEntity> createprepostcondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) throws UseApiException { + PrePostConditionDTO createdPrePostCondition = modelService.createPrePostCondition(modelName, prePostConditionDTO, className); + + // Wrap the created pre/post condition in an EntityModel for HATEOAS + EntityModel entityModel = EntityModel.of(createdPrePostCondition); + + // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + // Link to the classes listing for this model (also used as self since there's no single-prepostcondition GET) + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); + + // Link to create another pre/post condition in this model + entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("prepostcondition").withRel("create-prepostcondition")); + + // Link to invariants for this model + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withRel("invariants")); + + // Link to associations for this model + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + + @GetMapping("/model/{modelName}/prepostconditions") + public ResponseEntity>> getModelPrePostCond(@PathVariable String modelName) { + List prePostConditions = modelService.getModelPrePostConditions(modelName); + + List> prePostConditionEntities = prePostConditions.stream().map(prePostCondition -> { + EntityModel entityModel = EntityModel.of(prePostCondition); + + // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + // Self-link to this collection + entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCond(modelName)).withSelfRel()); + + // Link to classes + entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withRel("classes")); + + // Link to associations + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + + return entityModel; + }).collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(prePostConditionEntities); + + // Self-link for the collection + collectionModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCond(modelName)).withSelfRel()); + + return new ResponseEntity<>(collectionModel, HttpStatus.OK); + } + + @GetMapping("/model/{modelName}/prepostcondition/{prePostConditionName}") + public ResponseEntity> getModelPrePostCondByName(@PathVariable String modelName, @PathVariable String prePostConditionName) { + PrePostConditionDTO prePostCondition = modelService.getPrePostConditionByName(modelName, prePostConditionName); + EntityModel entityModel = EntityModel.of(prePostCondition); + entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCondByName(modelName, prePostConditionName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); + } + + /* Endpoints that are needed (prefix /api): POST /model - Create a new model :check: diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 81692fc6d..269861506 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -3,20 +3,11 @@ import lombok.RequiredArgsConstructor; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; -import org.tzi.use.DTO.AssociationDTO; -import org.tzi.use.DTO.ClassDTO; -import org.tzi.use.DTO.InvariantDTO; -import org.tzi.use.DTO.ModelDTO; +import org.tzi.use.DTO.*; import org.tzi.use.UseModelFacade; import org.tzi.use.api.UseApiException; -import org.tzi.use.entities.AssociationNTT; -import org.tzi.use.entities.ClassNTT; -import org.tzi.use.entities.InvariantNTT; -import org.tzi.use.entities.ModelNTT; -import org.tzi.use.mapper.AssociationMapperImpl; -import org.tzi.use.mapper.ClassMapperImpl; -import org.tzi.use.mapper.InvariantMapperImpl; -import org.tzi.use.mapper.ModelMapper; +import org.tzi.use.entities.*; +import org.tzi.use.mapper.*; import org.tzi.use.repository.ClassRepo; import org.tzi.use.repository.ModelRepo; @@ -33,6 +24,7 @@ public class ModelService { private final ClassMapperImpl classMapperImpl; private final InvariantMapperImpl invariantMapperImpl; private final AssociationMapperImpl associationMapperImpl; + private final PrePostConditionMapper prePostConditionMapper; /** @@ -146,4 +138,29 @@ public AssociationDTO createAssociation(String modelName, AssociationDTO associa modelRepo.save(modelOfAssociation.get()); return associationMapperImpl.toDTO(tmp_associationntt); } + + public PrePostConditionDTO createPrePostCondition(String modelName, PrePostConditionDTO prePostConditionDTO, String className) throws UseApiException { + PrePostConditionNTT tmp_prepostconditionntt = prePostConditionMapper.toEntity(prePostConditionDTO); + Optional modelOfPrePostCondition = modelRepo.findById(modelName); + UseModelFacade.createPrePostCondition(tmp_prepostconditionntt, className, modelName); + String name = className + "::" + prePostConditionDTO.getOperationName() + + prePostConditionDTO.getName(); + + modelOfPrePostCondition.get().getPrePostConditions().put(name, tmp_prepostconditionntt); + modelRepo.save(modelOfPrePostCondition.get()); + return prePostConditionMapper.toDTO(tmp_prepostconditionntt); + } + + public List getModelPrePostConditions(String modelName) { + Optional modelOpt = modelRepo.findById(modelName); + return modelOpt.get().getPrePostConditions().values().stream() + .map(prePostConditionMapper::toDTO) + .toList(); + } + + public PrePostConditionDTO getPrePostConditionByName(String modelName, String prePostConditionName) { + Optional modelOpt = modelRepo.findById(modelName); + PrePostConditionNTT prePostCondition = modelOpt.get().getPrePostConditions().get(prePostConditionName); + return prePostConditionMapper.toDTO(prePostCondition); + } } From 5af4a275720aa1178ec6e75047adac4c028a6759 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 27 Nov 2025 00:11:49 +0100 Subject: [PATCH 101/148] has to be DTO --- use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index f70a328ae..3eb989357 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -17,7 +17,7 @@ public class ModelDTO { private List classes = new ArrayList<>(); private List associations = new ArrayList<>(); private List invariants = new ArrayList<>(); - private Map prePostConditions = new TreeMap<>(); + private Map prePostConditions = new TreeMap<>(); public ModelDTO(String name) { this.name = name; From 2c121ea977558f2d5aa31f50cd69e29e4ff7a6ab Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 27 Nov 2025 02:30:51 +0100 Subject: [PATCH 102/148] wip --- .../main/java/org/tzi/use/UseModelFacade.java | 224 ++++++++++++------ .../java/org/tzi/use/entities/ModelNTT.java | 6 +- .../tzi/use/rest/services/ClassService.java | 7 +- .../tzi/use/rest/services/ModelService.java | 11 +- 4 files changed, 164 insertions(+), 84 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index fa3ff2d11..46d6a7764 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -1,63 +1,113 @@ package org.tzi.use; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.DTO.*; -import org.tzi.use.entities.AttributeNTT; -import org.tzi.use.entities.OperationNTT; -import org.tzi.use.entities.PrePostConditionNTT; -import org.tzi.use.uml.mm.MClass; +import org.tzi.use.entities.*; +import org.tzi.use.repository.ModelRepo; import java.util.HashMap; import java.util.Map; +@Component public class UseModelFacade { - // Cache UseModelApi instances per model name to maintain state - private static final Map modelApiCache = new HashMap<>(); + + @Autowired + private ModelRepo modelRepo; + private final Map modelNTTCache = new HashMap<>(); /** - * Gets or creates a UseModelApi instance for the given model name. - * This ensures we maintain the same model instance across multiple operations. + * Gets or creates a model API instance. + * First attempts to load from repository, then creates if not found. + * Caches the result for performance. */ - private static UseModelApi getOrCreateModelApi(String modelName) { - return modelApiCache.computeIfAbsent(modelName, name -> { - UseModelApi api = new UseModelApi(); - api.createModel(name); - return api; - }); - } + private ModelNTT getOrCreateModel(String modelName) { + return modelNTTCache.computeIfAbsent(modelName, name -> { + ModelNTT modelNTT = new ModelNTT(modelName); + + // Try to load existing model from repository + modelRepo.findById(name).ifPresent(model -> { + loadModelIntoCache(modelNTT, model); + }); - public static void createModel(String modelName) { - // Use getOrCreateModelApi to ensure idempotent behavior - getOrCreateModelApi(modelName); + return modelNTT; + }); } /** - * Creates a class in the specified model if it doesn't already exist. - * This is idempotent - calling it multiple times with the same parameters is safe. + * Loads a persisted model from the repository into the UseModelApi instance. + * This reconstructs the model structure (classes, attributes, operations, etc.) + * from the stored ModelNTT entity. * - * @param modelName The name of the model containing the class - * @param className The name of the class to create - * @throws UseApiException If there's an error creating the class + * @param modelNTT The UseModelApi instance to load the model into + * @param model The persisted ModelNTT entity from the repository */ - public static void createClass(String modelName, String className) throws UseApiException { - UseModelApi api = getOrCreateModelApi(modelName); + private void loadModelIntoCache(ModelNTT modelNTT, ModelNTT model) { + // Load all classes + if (model.getClasses() != null) { + for (ClassNTT classNTT : model.getClasses()) { + modelNTT.addClass(classNTT); + + // Load attributes for this class + if (classNTT.getAttributes() != null) { + for (AttributeNTT attribute : classNTT.getAttributes()) { + classNTT.getAttributes().add(attribute); + } + } + + // Load operations for this class + if (classNTT.getOperations() != null) { + for (OperationNTT operation : classNTT.getOperations()) { + classNTT.getOperations().add(operation); + } + } + } + } + + // Load associations + if (model.getAssociations() != null) { + for (AssociationNTT association : model.getAssociations()) { + modelNTT.getAssociations().add(association); + } + } + if (model.getInvariants() != null) { + for (InvariantNTT invariant : model.getInvariants()) { + modelNTT.getInvariants().add(invariant); + } + } + +// Load pre/post conditions + if (model.getPrePostConditions() != null) { + for (Map.Entry entry : model.getPrePostConditions().entrySet()) { + modelNTT.getPrePostConditions().put(entry.getKey(), entry.getValue()); + } + } - // Check if class already exists - MClass existingClass = api.getClass(className); - if (existingClass == null) { - api.createClass(className, false); - } - // If class already exists, do nothing (idempotent) } - public static void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { - UseModelApi api = getOrCreateModelApi(modelName); + + public void createModel(String modelName) { +// ModelNTT modelNTT = getOrCreateModel(modelName); + new UseModelApi().createModel(modelName); + } + + + public void createClass(String modelName, String className) throws UseApiException { + ModelNTT modelNTT = getOrCreateModel(modelName); + + UseModelApi useModelApi = loadUseModelApiFromModelNTT(modelNTT); + useModelApi.createClass(className,false); + } + + public void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { +// UseModelApi api = getOrCreateModel(modelName); createClass(modelName, className); // createOperation(modelName, className, new OperationNTT("calculateAge", new String[][]{}, "Boolean")); // Create a query operation WITH a body - api.createAttribute(className, "birthYear", "Integer"); +// api.createAttribute(className, "birthYear", "Integer"); // api.createAttribute(className, "calculateAge", "Integer"); // api.createQueryOperation( // className, @@ -76,61 +126,89 @@ public static void createInvariant(InvariantDTO invariantDTOreq, String classNam // // Replace the call to 'calculateAge' in the invariant with its actual OCL expression // String expandedInvBody = originalInvBody.replace("self.calculateAge", calculateAgeBody); - api.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); +// api.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); + // Save updated model to repository } - public static void createAssociation(AssociationDTO association, String modelName) throws UseApiException { - UseModelApi api = getOrCreateModelApi(modelName); + public void createAssociation(AssociationDTO association, String modelName) throws UseApiException { +// UseModelApi api = getOrCreateModel(modelName); + ModelNTT modelNTT = getOrCreateModel(modelName); + createClass(modelName, association.getEnd1ClassName()); createClass(modelName, association.getEnd2ClassName()); - api.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), - association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); +// api.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), +// association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); + + // Save updated model to repository } - public static void createAttribute(String modelName, String className, AttributeNTT attributeNTT) throws UseApiException { - UseModelApi api = getOrCreateModelApi(modelName); - createClass(modelName, className); - api.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); + public void createAttribute(String modelName, String className, AttributeNTT attributeNTT) throws UseApiException { + ModelNTT modelNTT = getOrCreateModel(modelName); + UseModelApi useModelApi = loadUseModelApiFromModelNTT(modelNTT); + useModelApi.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); + modelRepo.save(modelNTT); + // Save updated model to repository } + private UseModelApi loadUseModelApiFromModelNTT(ModelNTT modelNTT) throws UseApiException { + UseModelApi useModelApi = new UseModelApi(); + useModelApi.createModel(modelNTT.getName()); + + // Load classes + if (modelNTT.getClasses() != null) { + for (ClassNTT classNTT : modelNTT.getClasses()) { + useModelApi.createClass(classNTT.getName(), false); + + // Load attributes + if (classNTT.getAttributes() != null) { + for (AttributeNTT attribute : classNTT.getAttributes()) { + useModelApi.createAttribute(classNTT.getName(), attribute.getName(), attribute.getType()); + } + } + + // Load operations + if (classNTT.getOperations() != null) { + for (OperationNTT operation : classNTT.getOperations()) { + useModelApi.createOperation(classNTT.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); + } + } + } + } - public static void createOperation(String modelName, String className, OperationNTT operationNTT) throws UseApiException { - UseModelApi api = getOrCreateModelApi(modelName); - createClass(modelName, className); - api.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); - } + // Load associations + if (modelNTT.getAssociations() != null) { + for (AssociationNTT association : modelNTT.getAssociations()) { + useModelApi.createAssociation( + association.getAssociationName(), + association.getEnd1ClassName(), + association.getEnd1RoleName(), + association.getEnd1Multiplicity(), + association.getEnd1Aggregation().ordinal(), + association.getEnd2ClassName(), + association.getEnd2RoleName(), + association.getEnd2Multiplicity(), + association.getEnd2Aggregation().ordinal() + ); + } + } - /** - * Clears the cached model for the given model name. - * This is useful when you want to start fresh with a model. - * @param modelName The name of the model to clear - */ - public static void clearModel(String modelName) { - modelApiCache.remove(modelName); + return useModelApi; } - /** - * Clears all cached models. - * This is useful for testing or when you want to reset the entire state. - */ - public static void clearAllModels() { - modelApiCache.clear(); - } + public void createOperation(String modelName, String className, OperationNTT operationNTT) throws UseApiException { +// UseModelApi api = getOrCreateModel(modelName); + createClass(modelName, className); +// api.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); - /** - * Gets the UseModelApi instance for a specific model name. - * Returns null if the model hasn't been created yet. - * @param modelName The name of the model - * @return The UseModelApi instance or null if not found - */ - public static UseModelApi getModelApi(String modelName) { - return modelApiCache.get(modelName); + // Save updated model to repository } - public static void createPrePostCondition(PrePostConditionNTT ppc, String className, String modelName) throws UseApiException { - UseModelApi api = getOrCreateModelApi(modelName); + public void createPrePostCondition(PrePostConditionNTT ppc, String className, String modelName) throws UseApiException { +// UseModelApi api = getOrCreateModel(modelName); createClass(modelName, className); - api.createPrePostCondition(className,ppc.getOperationName(),ppc.getName(), ppc.getCondition(), ppc.isPre()); +// api.createPrePostCondition(className, ppc.getOperationName(), ppc.getName(), ppc.getCondition(), ppc.isPre()); + } + } diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index be4fbd087..d38695acd 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -32,14 +32,14 @@ public ModelNTT(String name) { } - public void addClass(ClassNTT classDTO) { - if (classDTO == null) { + public void addClass(ClassNTT classNTT) { + if (classNTT == null) { return; } if (this.classes == null) { this.classes = new ArrayList<>(); } - this.classes.add(classDTO); + this.classes.add(classNTT); } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index b2bdffb66..f47ccddbf 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -20,11 +20,12 @@ @RequiredArgsConstructor public class ClassService { private final ClassRepo classRepo; - private final ModelRepo modelRepo; // added to resolve model by class name + private final ModelRepo modelRepo; private final ClassMapper classMapper; private final AttributeMapper attributeMapper; private final OperationMapper operationMapper; private final PrePostConditionMapper prePostConditionMapper; + private final UseModelFacade useModelFacade; public ClassDTO getClassByName(String className) { ClassNTT classNTT = classRepo.findById(className) @@ -55,7 +56,7 @@ public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); // Resolve model name that contains this class String modelName = getModelNameForClass(className); - UseModelFacade.createAttribute(modelName, className, attributeNTT); + useModelFacade.createAttribute(modelName, className, attributeNTT); classNTT.getAttributes().add(attributeNTT); classRepo.save(classNTT); return attributeMapper.toDTO(attributeNTT); @@ -73,7 +74,7 @@ public OperationDTO createOperation(String className, OperationDTO operationDTO) .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); String modelName = getModelNameForClass(className); - UseModelFacade.createOperation(modelName, className, operationNTT); + useModelFacade.createOperation(modelName, className, operationNTT); classNTT.getOperations().add(operationNTT); classRepo.save(classNTT); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 269861506..f52b8a3b4 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -25,6 +25,7 @@ public class ModelService { private final InvariantMapperImpl invariantMapperImpl; private final AssociationMapperImpl associationMapperImpl; private final PrePostConditionMapper prePostConditionMapper; + private final UseModelFacade useModelFacade; /** @@ -40,7 +41,7 @@ public ModelDTO createModel(ModelDTO modelDTOreq) { } ModelNTT tmp_modelntt = modelMapper.toEntity(modelDTOreq); - UseModelFacade.createModel(tmp_modelntt.getName()); + useModelFacade.createModel(tmp_modelntt.getName()); modelRepo.save(tmp_modelntt); return modelMapper.toDTO(tmp_modelntt); @@ -59,7 +60,7 @@ public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseAp // // if the class has attributed and operations this would not be enough // UseModelFacade.createClass(tmp_classntt.getName()); // Create the class in the USE model (now with proper model context) - UseModelFacade.createClass(modelName, tmp_classntt.getName()); + useModelFacade.createClass(modelName, tmp_classntt.getName()); modelOfClass.get().addClass(tmp_classntt); modelRepo.save(modelOfClass.get()); @@ -123,7 +124,7 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr // find the class inside the model by className //TODO wenn die facade ein error bekommt wird die zeile darunter ausgeführt? - UseModelFacade.createInvariant(invariantDTOreq, className, modelName); + useModelFacade.createInvariant(invariantDTOreq, className, modelName); modelOfInvariant.get().getInvariants().add(tmp_invariantntt); //TODO modelRepo.save(modelOfInvariant.get()); @@ -133,7 +134,7 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr public AssociationDTO createAssociation(String modelName, AssociationDTO association) throws UseApiException { AssociationNTT tmp_associationntt = associationMapperImpl.toEntity(association); Optional modelOfAssociation = modelRepo.findById(modelName); - UseModelFacade.createAssociation(association, modelName); + useModelFacade.createAssociation(association, modelName); modelOfAssociation.get().getAssociations().add(tmp_associationntt); modelRepo.save(modelOfAssociation.get()); return associationMapperImpl.toDTO(tmp_associationntt); @@ -142,7 +143,7 @@ public AssociationDTO createAssociation(String modelName, AssociationDTO associa public PrePostConditionDTO createPrePostCondition(String modelName, PrePostConditionDTO prePostConditionDTO, String className) throws UseApiException { PrePostConditionNTT tmp_prepostconditionntt = prePostConditionMapper.toEntity(prePostConditionDTO); Optional modelOfPrePostCondition = modelRepo.findById(modelName); - UseModelFacade.createPrePostCondition(tmp_prepostconditionntt, className, modelName); + useModelFacade.createPrePostCondition(tmp_prepostconditionntt, className, modelName); String name = className + "::" + prePostConditionDTO.getOperationName() + prePostConditionDTO.getName(); From 9fb9f8bc190b803984aebda32503e55b2d4b8c7a Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 1 Dec 2025 01:48:58 +0100 Subject: [PATCH 103/148] removed wrong and not needed --- .../org/tzi/use/DTO/PrePostConditionDTO.java | 2 - .../org/tzi/use/entities/AssociationNTT.java | 4 -- .../org/tzi/use/entities/AttributeNTT.java | 2 - .../java/org/tzi/use/entities/ClassNTT.java | 7 --- .../org/tzi/use/entities/InvariantNTT.java | 4 -- .../org/tzi/use/entities/OperationNTT.java | 2 - .../tzi/use/entities/PrePostConditionNTT.java | 3 - .../org/tzi/use/repository/ClassRepo.java | 7 --- .../tzi/use/rest/services/ClassService.java | 60 ++++++++++++------- .../tzi/use/rest/services/ModelService.java | 26 ++++---- 10 files changed, 52 insertions(+), 65 deletions(-) delete mode 100644 use-api/src/main/java/org/tzi/use/repository/ClassRepo.java diff --git a/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java b/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java index 2ff38621d..ce810346c 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/PrePostConditionDTO.java @@ -1,10 +1,8 @@ package org.tzi.use.DTO; -import jakarta.persistence.Id; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.mongodb.core.mapping.Document; @Data @NoArgsConstructor diff --git a/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java b/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java index 511aaa651..ae7956db2 100644 --- a/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/AssociationNTT.java @@ -3,15 +3,11 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; -@Document("association") @Data @AllArgsConstructor @NoArgsConstructor public class AssociationNTT { - @Id private String associationName; private String end1ClassName; diff --git a/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java b/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java index 0606e06d5..16bf70284 100644 --- a/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/AttributeNTT.java @@ -3,9 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.mongodb.core.mapping.Document; -@Document("attribute") @Data @NoArgsConstructor @AllArgsConstructor diff --git a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java index 394b131ac..75b734956 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ClassNTT.java @@ -3,21 +3,14 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.mapping.Document; -import org.tzi.use.DTO.AssociationDTO; -import org.tzi.use.DTO.AttributeDTO; -import org.tzi.use.DTO.OperationDTO; import java.util.ArrayList; import java.util.List; -@Document("class") @Data @AllArgsConstructor @NoArgsConstructor public class ClassNTT { - @Id private String name; private List attributes = new ArrayList<>(); private List operations = new ArrayList<>(); diff --git a/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java b/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java index 45fa94115..8b0ef79c8 100644 --- a/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/InvariantNTT.java @@ -1,17 +1,13 @@ package org.tzi.use.entities; -import org.springframework.data.annotation.Id; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.mongodb.core.mapping.Document; -@Document("invariant") @Data @AllArgsConstructor @NoArgsConstructor public class InvariantNTT { - @Id private String invName; private String invBody; private boolean isExistential; diff --git a/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java b/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java index 5de2960c7..bc9c3db98 100644 --- a/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/OperationNTT.java @@ -3,9 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.mongodb.core.mapping.Document; -@Document("operation") @Data @NoArgsConstructor @AllArgsConstructor diff --git a/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java b/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java index dafafe2dd..f30784495 100644 --- a/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/PrePostConditionNTT.java @@ -1,12 +1,9 @@ package org.tzi.use.entities; -import org.springframework.data.annotation.Id; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.mongodb.core.mapping.Document; -@Document("prepostcondition") @Data @AllArgsConstructor @NoArgsConstructor diff --git a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java b/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java deleted file mode 100644 index 96cc3cb0a..000000000 --- a/use-api/src/main/java/org/tzi/use/repository/ClassRepo.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.tzi.use.repository; - -import org.springframework.data.mongodb.repository.MongoRepository; -import org.tzi.use.entities.ClassNTT; - -public interface ClassRepo extends MongoRepository { -} diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index f47ccddbf..ad1bf441f 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -9,9 +9,9 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.entities.AttributeNTT; import org.tzi.use.entities.ClassNTT; +import org.tzi.use.entities.ModelNTT; import org.tzi.use.entities.OperationNTT; import org.tzi.use.mapper.*; -import org.tzi.use.repository.ClassRepo; import org.tzi.use.repository.ModelRepo; import java.util.List; @@ -19,7 +19,6 @@ @Service @RequiredArgsConstructor public class ClassService { - private final ClassRepo classRepo; private final ModelRepo modelRepo; private final ClassMapper classMapper; private final AttributeMapper attributeMapper; @@ -28,19 +27,31 @@ public class ClassService { private final UseModelFacade useModelFacade; public ClassDTO getClassByName(String className) { - ClassNTT classNTT = classRepo.findById(className) + ModelNTT model = modelRepo.findByClassesName(className) + .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); + ClassNTT classNTT = model.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); return classMapper.toDTO(classNTT); } public List getAttributes(String className) { - ClassNTT classNTT = classRepo.findById(className) + ModelNTT model = modelRepo.findByClassesName(className) + .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); + ClassNTT classNTT = model.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); return classNTT.getAttributes().stream().map(attributeMapper::toDTO).toList(); } public List getOperations(String className) { - ClassNTT classNTT = classRepo.findById(className) + ModelNTT model = modelRepo.findByClassesName(className) + .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); + ClassNTT classNTT = model.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); return classNTT.getOperations().stream().map(operationMapper::toDTO).toList(); } @@ -52,32 +63,41 @@ public List getOperations(String className) { public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) throws UseApiException { AttributeNTT attributeNTT = attributeMapper.toEntity(attributeDTO); - ClassNTT classNTT = classRepo.findById(className) + + // Find model containing this class + ModelNTT model = modelRepo.findByClassesName(className) + .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); + ClassNTT classNTT = model.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - // Resolve model name that contains this class - String modelName = getModelNameForClass(className); - useModelFacade.createAttribute(modelName, className, attributeNTT); + + // Create attribute in USE model + useModelFacade.createAttribute(model.getName(), className, attributeNTT); + + // Add to entity and save through model classNTT.getAttributes().add(attributeNTT); - classRepo.save(classNTT); + modelRepo.save(model); return attributeMapper.toDTO(attributeNTT); } - private String getModelNameForClass(String className) { - return modelRepo.findByClassesName(className) - .map(m -> m.getName()) - .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); - } - public OperationDTO createOperation(String className, OperationDTO operationDTO) throws UseApiException { OperationNTT operationNTT = operationMapper.toEntity(operationDTO); - ClassNTT classNTT = classRepo.findById(className) + + // Find model containing this class + ModelNTT model = modelRepo.findByClassesName(className) + .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); + ClassNTT classNTT = model.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - String modelName = getModelNameForClass(className); - useModelFacade.createOperation(modelName, className, operationNTT); + // Create operation in USE model + useModelFacade.createOperation(model.getName(), className, operationNTT); + // Add to entity and save through model classNTT.getOperations().add(operationNTT); - classRepo.save(classNTT); + modelRepo.save(model); return operationMapper.toDTO(operationNTT); } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index f52b8a3b4..d6b9ef59c 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -8,7 +8,6 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.entities.*; import org.tzi.use.mapper.*; -import org.tzi.use.repository.ClassRepo; import org.tzi.use.repository.ModelRepo; import java.util.List; @@ -19,7 +18,6 @@ public class ModelService { private final ModelRepo modelRepo; - private final ClassRepo classRepo; private final ModelMapper modelMapper; private final ClassMapperImpl classMapperImpl; private final InvariantMapperImpl invariantMapperImpl; @@ -48,23 +46,23 @@ public ModelDTO createModel(ModelDTO modelDTOreq) { } public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseApiException { - if(classRepo.findById(classDTOreq.getName()).isPresent()) { - throw new DuplicateKeyException("Class name already exists"); - } - ClassNTT tmp_classntt = classMapperImpl.toEntity(classDTOreq); - Optional modelOfClass = modelRepo.findById(modelName); - //check for modelOfClass presence is nessary? -> I think no because cannot create model via api if it doesn't exist + ModelNTT modelOfClass = modelRepo.findById(modelName) + .orElseThrow(() -> new IllegalArgumentException("Model not found: " + modelName)); + + // Check if class already exists in this model + boolean classExists = modelOfClass.getClasses().stream() + .anyMatch(c -> c.getName().equals(classDTOreq.getName())); + if (classExists) { + throw new DuplicateKeyException("Class name already exists in model: " + modelName); + } -// // if the class has attributed and operations this would not be enough -// UseModelFacade.createClass(tmp_classntt.getName()); - // Create the class in the USE model (now with proper model context) + // Create the class in the USE model useModelFacade.createClass(modelName, tmp_classntt.getName()); - modelOfClass.get().addClass(tmp_classntt); + modelOfClass.addClass(tmp_classntt); - modelRepo.save(modelOfClass.get()); - classRepo.save(tmp_classntt); + modelRepo.save(modelOfClass); return classMapperImpl.toDTO(tmp_classntt); } From a462a660e34c3b7454d96a396d4ea715a4fc421a Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 1 Dec 2025 02:02:41 +0100 Subject: [PATCH 104/148] code cleanup and new method --- .../main/java/org/tzi/use/UseModelFacade.java | 84 +++++++++---------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 46d6a7764..bd2937def 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -2,9 +2,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.tzi.use.DTO.AssociationDTO; +import org.tzi.use.DTO.InvariantDTO; import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; -import org.tzi.use.DTO.*; import org.tzi.use.entities.*; import org.tzi.use.repository.ModelRepo; @@ -14,9 +15,16 @@ @Component public class UseModelFacade { + private final Map modelNTTCache = new HashMap<>(); @Autowired private ModelRepo modelRepo; - private final Map modelNTTCache = new HashMap<>(); + + private UseModelApi createUMAfromModelNTT(ModelNTT modelNTT) { + UseModelApi result = new UseModelApi(modelNTT.getName()); + + return result; + } + /** * Gets or creates a model API instance. @@ -42,48 +50,48 @@ private ModelNTT getOrCreateModel(String modelName) { * from the stored ModelNTT entity. * * @param modelNTT The UseModelApi instance to load the model into - * @param model The persisted ModelNTT entity from the repository + * @param model The persisted ModelNTT entity from the repository */ private void loadModelIntoCache(ModelNTT modelNTT, ModelNTT model) { - // Load all classes - if (model.getClasses() != null) { - for (ClassNTT classNTT : model.getClasses()) { - modelNTT.addClass(classNTT); - - // Load attributes for this class - if (classNTT.getAttributes() != null) { - for (AttributeNTT attribute : classNTT.getAttributes()) { - classNTT.getAttributes().add(attribute); - } + // Load all classes + if (model.getClasses() != null) { + for (ClassNTT classNTT : model.getClasses()) { + modelNTT.addClass(classNTT); + + // Load attributes for this class + if (classNTT.getAttributes() != null) { + for (AttributeNTT attribute : classNTT.getAttributes()) { + classNTT.getAttributes().add(attribute); } + } - // Load operations for this class - if (classNTT.getOperations() != null) { - for (OperationNTT operation : classNTT.getOperations()) { - classNTT.getOperations().add(operation); - } + // Load operations for this class + if (classNTT.getOperations() != null) { + for (OperationNTT operation : classNTT.getOperations()) { + classNTT.getOperations().add(operation); } } } + } - // Load associations - if (model.getAssociations() != null) { - for (AssociationNTT association : model.getAssociations()) { - modelNTT.getAssociations().add(association); - } + // Load associations + if (model.getAssociations() != null) { + for (AssociationNTT association : model.getAssociations()) { + modelNTT.getAssociations().add(association); } - if (model.getInvariants() != null) { - for (InvariantNTT invariant : model.getInvariants()) { - modelNTT.getInvariants().add(invariant); - } + } + if (model.getInvariants() != null) { + for (InvariantNTT invariant : model.getInvariants()) { + modelNTT.getInvariants().add(invariant); } + } // Load pre/post conditions - if (model.getPrePostConditions() != null) { - for (Map.Entry entry : model.getPrePostConditions().entrySet()) { - modelNTT.getPrePostConditions().put(entry.getKey(), entry.getValue()); - } + if (model.getPrePostConditions() != null) { + for (Map.Entry entry : model.getPrePostConditions().entrySet()) { + modelNTT.getPrePostConditions().put(entry.getKey(), entry.getValue()); } + } } @@ -98,7 +106,7 @@ public void createClass(String modelName, String className) throws UseApiExcepti ModelNTT modelNTT = getOrCreateModel(modelName); UseModelApi useModelApi = loadUseModelApiFromModelNTT(modelNTT); - useModelApi.createClass(className,false); + useModelApi.createClass(className, false); } public void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { @@ -179,17 +187,7 @@ private UseModelApi loadUseModelApiFromModelNTT(ModelNTT modelNTT) throws UseApi // Load associations if (modelNTT.getAssociations() != null) { for (AssociationNTT association : modelNTT.getAssociations()) { - useModelApi.createAssociation( - association.getAssociationName(), - association.getEnd1ClassName(), - association.getEnd1RoleName(), - association.getEnd1Multiplicity(), - association.getEnd1Aggregation().ordinal(), - association.getEnd2ClassName(), - association.getEnd2RoleName(), - association.getEnd2Multiplicity(), - association.getEnd2Aggregation().ordinal() - ); + useModelApi.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); } } From 394b0a568219e3af419eb8d59b63bf73589de951 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 1 Dec 2025 15:59:41 +0100 Subject: [PATCH 105/148] model objects and facade changed the modelntt and dto to fit the mmodel better usemodelfacade overhaul, now recreating the Usemodelapi before working on it --- .../main/java/org/tzi/use/DTO/ModelDTO.java | 7 +- .../main/java/org/tzi/use/UseModelFacade.java | 207 ++++-------------- .../java/org/tzi/use/entities/ModelNTT.java | 6 +- 3 files changed, 48 insertions(+), 172 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java index 3eb989357..9e61a79aa 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ModelDTO.java @@ -1,6 +1,7 @@ package org.tzi.use.DTO; import lombok.*; +import org.tzi.use.entities.AssociationNTT; import org.tzi.use.entities.InvariantNTT; import org.tzi.use.entities.PrePostConditionNTT; @@ -15,9 +16,9 @@ public class ModelDTO { private String name; private List classes = new ArrayList<>(); - private List associations = new ArrayList<>(); - private List invariants = new ArrayList<>(); - private Map prePostConditions = new TreeMap<>(); + private Map associations = new TreeMap<>(); + private Map invariants = new TreeMap<>(); + private Map prePostConditions = new TreeMap<>(); public ModelDTO(String name) { this.name = name; diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index bd2937def..a616bf7f1 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -1,13 +1,11 @@ package org.tzi.use; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tzi.use.DTO.AssociationDTO; import org.tzi.use.DTO.InvariantDTO; import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.entities.*; -import org.tzi.use.repository.ModelRepo; import java.util.HashMap; import java.util.Map; @@ -15,198 +13,77 @@ @Component public class UseModelFacade { - private final Map modelNTTCache = new HashMap<>(); - @Autowired - private ModelRepo modelRepo; + private final Map umaCache = new HashMap<>(); - private UseModelApi createUMAfromModelNTT(ModelNTT modelNTT) { - UseModelApi result = new UseModelApi(modelNTT.getName()); - - return result; + private static String extractClassName(String concatedClassName) { + String[] parts = concatedClassName.split("::"); + return parts[0]; } + private UseModelApi getUMAfromModelNTT(ModelNTT modelNTT) throws UseApiException { - /** - * Gets or creates a model API instance. - * First attempts to load from repository, then creates if not found. - * Caches the result for performance. - */ - private ModelNTT getOrCreateModel(String modelName) { - return modelNTTCache.computeIfAbsent(modelName, name -> { - ModelNTT modelNTT = new ModelNTT(modelName); - - // Try to load existing model from repository - modelRepo.findById(name).ifPresent(model -> { - loadModelIntoCache(modelNTT, model); - }); + if (umaCache.containsKey(modelNTT.getName())) return umaCache.get(modelNTT.getName()); - return modelNTT; - }); - } - - /** - * Loads a persisted model from the repository into the UseModelApi instance. - * This reconstructs the model structure (classes, attributes, operations, etc.) - * from the stored ModelNTT entity. - * - * @param modelNTT The UseModelApi instance to load the model into - * @param model The persisted ModelNTT entity from the repository - */ - private void loadModelIntoCache(ModelNTT modelNTT, ModelNTT model) { - // Load all classes - if (model.getClasses() != null) { - for (ClassNTT classNTT : model.getClasses()) { - modelNTT.addClass(classNTT); - - // Load attributes for this class - if (classNTT.getAttributes() != null) { - for (AttributeNTT attribute : classNTT.getAttributes()) { - classNTT.getAttributes().add(attribute); - } - } - - // Load operations for this class - if (classNTT.getOperations() != null) { - for (OperationNTT operation : classNTT.getOperations()) { - classNTT.getOperations().add(operation); - } - } + UseModelApi result = new UseModelApi(modelNTT.getName()); + for (ClassNTT aClass : modelNTT.getClasses()) { + result.createClass(aClass.getName(), false); + for (AttributeNTT attribute : aClass.getAttributes()) { + result.createAttribute(aClass.getName(), attribute.getName(), attribute.getType()); } - } - - // Load associations - if (model.getAssociations() != null) { - for (AssociationNTT association : model.getAssociations()) { - modelNTT.getAssociations().add(association); + for (OperationNTT operation : aClass.getOperations()) { + result.createOperation(aClass.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); } } - if (model.getInvariants() != null) { - for (InvariantNTT invariant : model.getInvariants()) { - modelNTT.getInvariants().add(invariant); - } + for (Map.Entry ppcClass : modelNTT.getPrePostConditions().entrySet()) { + result.createPrePostCondition(extractClassName(ppcClass.getKey()), ppcClass.getValue().getOperationName(), ppcClass.getValue().getName(), ppcClass.getValue().getCondition(), ppcClass.getValue().isPre()); } -// Load pre/post conditions - if (model.getPrePostConditions() != null) { - for (Map.Entry entry : model.getPrePostConditions().entrySet()) { - modelNTT.getPrePostConditions().put(entry.getKey(), entry.getValue()); - } + for (Map.Entry assocClass : modelNTT.getAssociations().entrySet()) { + result.createAssociation(assocClass.getValue().getAssociationName(), assocClass.getValue().getEnd1ClassName(), assocClass.getValue().getEnd1RoleName(), assocClass.getValue().getEnd1Multiplicity(), assocClass.getValue().getEnd1Aggregation().ordinal(), assocClass.getValue().getEnd2ClassName(), assocClass.getValue().getEnd2RoleName(), assocClass.getValue().getEnd2Multiplicity(), assocClass.getValue().getEnd2Aggregation().ordinal()); } - } + for (Map.Entry invariantClass : modelNTT.getInvariants().entrySet()) { + result.createInvariant(invariantClass.getValue().getInvName(), extractClassName(invariantClass.getKey()), invariantClass.getValue().getInvBody(), invariantClass.getValue().isExistential()); + } + umaCache.put(modelNTT.getName(), result); + return result; + } public void createModel(String modelName) { -// ModelNTT modelNTT = getOrCreateModel(modelName); + //TOOD what do to when creating a new model? new UseModelApi().createModel(modelName); } - public void createClass(String modelName, String className) throws UseApiException { - ModelNTT modelNTT = getOrCreateModel(modelName); - - UseModelApi useModelApi = loadUseModelApiFromModelNTT(modelNTT); - useModelApi.createClass(className, false); + public void createClass(ModelNTT modelNTT, String className) throws UseApiException { + UseModelApi uma = getUMAfromModelNTT(modelNTT); + uma.createClass(className, false); } - public void createInvariant(InvariantDTO invariantDTOreq, String className, String modelName) throws UseApiException { -// UseModelApi api = getOrCreateModel(modelName); - createClass(modelName, className); - -// createOperation(modelName, className, new OperationNTT("calculateAge", new String[][]{}, "Boolean")); - // Create a query operation WITH a body -// api.createAttribute(className, "birthYear", "Integer"); -// api.createAttribute(className, "calculateAge", "Integer"); -// api.createQueryOperation( -// className, -// "calculateAge", -// new String[][]{}, // no parameters -// "Integer", // return type (should be Integer, not Boolean) -// "(2024 - self.birthYear)", // the actual implementation -// false // not a constructor -// ); -// // The invariant body from the request is "self.calculateAge >= 18" -// String originalInvBody = invariantDTOreq.getInvBody(); -// -// // The definition of the 'calculateAge' operation -// String calculateAgeBody = "(2024 - self.birthYear)"; -// -// // Replace the call to 'calculateAge' in the invariant with its actual OCL expression -// String expandedInvBody = originalInvBody.replace("self.calculateAge", calculateAgeBody); - -// api.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); - - // Save updated model to repository + public void createInvariant(InvariantDTO invariantDTOreq, String className, ModelNTT modelNTT) throws UseApiException { + UseModelApi uma = getUMAfromModelNTT(modelNTT); + uma.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); } - public void createAssociation(AssociationDTO association, String modelName) throws UseApiException { -// UseModelApi api = getOrCreateModel(modelName); - ModelNTT modelNTT = getOrCreateModel(modelName); - - createClass(modelName, association.getEnd1ClassName()); - createClass(modelName, association.getEnd2ClassName()); -// api.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), -// association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); - - // Save updated model to repository + public void createAssociation(AssociationDTO association, ModelNTT modelNTT) throws UseApiException { + UseModelApi uma = getUMAfromModelNTT(modelNTT); + uma.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); } - public void createAttribute(String modelName, String className, AttributeNTT attributeNTT) throws UseApiException { - ModelNTT modelNTT = getOrCreateModel(modelName); - UseModelApi useModelApi = loadUseModelApiFromModelNTT(modelNTT); - useModelApi.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); - modelRepo.save(modelNTT); - // Save updated model to repository - } - - private UseModelApi loadUseModelApiFromModelNTT(ModelNTT modelNTT) throws UseApiException { - UseModelApi useModelApi = new UseModelApi(); - useModelApi.createModel(modelNTT.getName()); - - // Load classes - if (modelNTT.getClasses() != null) { - for (ClassNTT classNTT : modelNTT.getClasses()) { - useModelApi.createClass(classNTT.getName(), false); - - // Load attributes - if (classNTT.getAttributes() != null) { - for (AttributeNTT attribute : classNTT.getAttributes()) { - useModelApi.createAttribute(classNTT.getName(), attribute.getName(), attribute.getType()); - } - } - - // Load operations - if (classNTT.getOperations() != null) { - for (OperationNTT operation : classNTT.getOperations()) { - useModelApi.createOperation(classNTT.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); - } - } - } - } - - // Load associations - if (modelNTT.getAssociations() != null) { - for (AssociationNTT association : modelNTT.getAssociations()) { - useModelApi.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); - } - } - - return useModelApi; + public void createAttribute(ModelNTT modelNTT, String className, AttributeNTT attributeNTT) throws UseApiException { + UseModelApi uma = getUMAfromModelNTT(modelNTT); + uma.createAttribute(className, attributeNTT.getName(), attributeNTT.getType()); } - public void createOperation(String modelName, String className, OperationNTT operationNTT) throws UseApiException { -// UseModelApi api = getOrCreateModel(modelName); - createClass(modelName, className); -// api.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); - - // Save updated model to repository + public void createOperation(ModelNTT modelNTT, String className, OperationNTT operationNTT) throws UseApiException { + UseModelApi uma = getUMAfromModelNTT(modelNTT); + uma.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); } - public void createPrePostCondition(PrePostConditionNTT ppc, String className, String modelName) throws UseApiException { -// UseModelApi api = getOrCreateModel(modelName); - createClass(modelName, className); -// api.createPrePostCondition(className, ppc.getOperationName(), ppc.getName(), ppc.getCondition(), ppc.isPre()); - + public void createPrePostCondition(PrePostConditionNTT ppc, String className, ModelNTT modelNTT) throws UseApiException { + UseModelApi uma = getUMAfromModelNTT(modelNTT); + uma.createPrePostCondition(className, ppc.getOperationName(), ppc.getName(), ppc.getCondition(), ppc.isPre()); } } diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index d38695acd..5ad80edd7 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -21,10 +21,8 @@ public class ModelNTT { @Id private String name; private List classes = new ArrayList<>(); - // String treemap - private List associations = new ArrayList<>(); - // String treemap - private List invariants = new ArrayList<>(); + private Map associations = new TreeMap<>(); + private Map invariants = new TreeMap<>(); private Map prePostConditions = new TreeMap<>(); public ModelNTT(String name) { From bee8a218788612e2e04c538dbd2b4ca2a5dc5090 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 1 Dec 2025 20:43:20 +0100 Subject: [PATCH 106/148] tmp fix the issues here --- .../org/tzi/use/rest/services/ClassService.java | 4 ++-- .../org/tzi/use/rest/services/ModelService.java | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index ad1bf441f..f1d836ca4 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -73,7 +73,7 @@ public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); // Create attribute in USE model - useModelFacade.createAttribute(model.getName(), className, attributeNTT); + useModelFacade.createAttribute(model, className, attributeNTT); // Add to entity and save through model classNTT.getAttributes().add(attributeNTT); @@ -93,7 +93,7 @@ public OperationDTO createOperation(String className, OperationDTO operationDTO) .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); // Create operation in USE model - useModelFacade.createOperation(model.getName(), className, operationNTT); + useModelFacade.createOperation(model, className, operationNTT); // Add to entity and save through model classNTT.getOperations().add(operationNTT); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index d6b9ef59c..d21b9806a 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -59,7 +59,7 @@ public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseAp } // Create the class in the USE model - useModelFacade.createClass(modelName, tmp_classntt.getName()); + useModelFacade.createClass(modelOfClass, tmp_classntt.getName()); modelOfClass.addClass(tmp_classntt); modelRepo.save(modelOfClass); @@ -105,12 +105,12 @@ public List getModelClasses(String modelName){ public List getModelAssociations(String modelName) { Optional modelOpt = modelRepo.findById(modelName); - return modelOpt.get().getAssociations().stream().map(associationMapperImpl::toDTO).toList(); +return modelOpt.get().getAssociations().values().stream().map(associationMapperImpl::toDTO).toList(); } public List getModelInvariants (String modelName) { Optional modelOpt = modelRepo.findById(modelName); - return modelOpt.get().getInvariants().stream() + return modelOpt.get().getInvariants().values().stream() .map(invariantMapperImpl::toDTO) .toList(); } @@ -122,8 +122,8 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr // find the class inside the model by className //TODO wenn die facade ein error bekommt wird die zeile darunter ausgeführt? - useModelFacade.createInvariant(invariantDTOreq, className, modelName); - modelOfInvariant.get().getInvariants().add(tmp_invariantntt); + useModelFacade.createInvariant(invariantDTOreq, className, modelOfInvariant.get()); + modelOfInvariant.get().getInvariants().put(className, tmp_invariantntt); //TODO modelRepo.save(modelOfInvariant.get()); return invariantMapperImpl.toDTO(tmp_invariantntt); @@ -132,8 +132,9 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr public AssociationDTO createAssociation(String modelName, AssociationDTO association) throws UseApiException { AssociationNTT tmp_associationntt = associationMapperImpl.toEntity(association); Optional modelOfAssociation = modelRepo.findById(modelName); - useModelFacade.createAssociation(association, modelName); - modelOfAssociation.get().getAssociations().add(tmp_associationntt); + useModelFacade.createAssociation(association, modelOfAssociation.get()); + modelOfAssociation.get().getAssociations().put(tmp_associationntt.getEnd2ClassName(),tmp_associationntt); + modelOfAssociation.get().getAssociations().put(tmp_associationntt.getEnd1ClassName(), tmp_associationntt); modelRepo.save(modelOfAssociation.get()); return associationMapperImpl.toDTO(tmp_associationntt); } @@ -141,7 +142,7 @@ public AssociationDTO createAssociation(String modelName, AssociationDTO associa public PrePostConditionDTO createPrePostCondition(String modelName, PrePostConditionDTO prePostConditionDTO, String className) throws UseApiException { PrePostConditionNTT tmp_prepostconditionntt = prePostConditionMapper.toEntity(prePostConditionDTO); Optional modelOfPrePostCondition = modelRepo.findById(modelName); - useModelFacade.createPrePostCondition(tmp_prepostconditionntt, className, modelName); + useModelFacade.createPrePostCondition(tmp_prepostconditionntt, className, modelOfPrePostCondition.get()); String name = className + "::" + prePostConditionDTO.getOperationName() + prePostConditionDTO.getName(); From a4b65b26d6c1a5190fe599862ff5d08a04b7eb2c Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 2 Dec 2025 15:17:48 +0100 Subject: [PATCH 107/148] clean ups --- use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java | 1 - .../src/main/java/org/tzi/use/entities/ModelNTT.java | 12 ------------ .../java/org/tzi/use/rest/services/ModelService.java | 2 +- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java index c2c95b503..e9d194f5f 100644 --- a/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java +++ b/use-api/src/main/java/org/tzi/use/DTO/ClassDTO.java @@ -14,5 +14,4 @@ public class ClassDTO { private List attributes = new ArrayList<>(); private List operations = new ArrayList<>(); private List associations = new ArrayList<>(); -// private List prepostcondition = new ArrayList<>(); } diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index 5ad80edd7..a59bc39b9 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -28,16 +28,4 @@ public class ModelNTT { public ModelNTT(String name) { this.name = name; } - - - public void addClass(ClassNTT classNTT) { - if (classNTT == null) { - return; - } - if (this.classes == null) { - this.classes = new ArrayList<>(); - } - this.classes.add(classNTT); - } - } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index d21b9806a..a578d46c7 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -60,7 +60,7 @@ public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseAp // Create the class in the USE model useModelFacade.createClass(modelOfClass, tmp_classntt.getName()); - modelOfClass.addClass(tmp_classntt); + modelOfClass.getClasses().add(tmp_classntt); modelRepo.save(modelOfClass); return classMapperImpl.toDTO(tmp_classntt); From 60195ac409081fb97524155005f240eb2299cb93 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 2 Dec 2025 15:41:01 +0100 Subject: [PATCH 108/148] renaming of the main --- use-api/pom.xml | 2 +- .../main/java/org/tzi/use/UseWebAPIApplication.java | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 use-api/src/main/java/org/tzi/use/UseWebAPIApplication.java diff --git a/use-api/pom.xml b/use-api/pom.xml index b54f4ccc7..17b6807c4 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -145,7 +145,7 @@ spring-boot-maven-plugin true - org.tzi.use.UseAPIApplication + org.tzi.use.UseWebAPIApplication diff --git a/use-api/src/main/java/org/tzi/use/UseWebAPIApplication.java b/use-api/src/main/java/org/tzi/use/UseWebAPIApplication.java new file mode 100644 index 000000000..0ba75b84e --- /dev/null +++ b/use-api/src/main/java/org/tzi/use/UseWebAPIApplication.java @@ -0,0 +1,11 @@ +package org.tzi.use; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class UseWebAPIApplication { + public static void main(String[] args) { + SpringApplication.run(UseWebAPIApplication.class, args); + } +} From 27603e2112ff1be2d4f66826a7724a08d4f60c9b Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 2 Dec 2025 15:41:21 +0100 Subject: [PATCH 109/148] removed and renamed --- .../java/org/tzi/use/UseAPIApplication.java | 24 ------------------- .../rest/exception/RestExceptionHandler.java | 1 - 2 files changed, 25 deletions(-) delete mode 100644 use-api/src/main/java/org/tzi/use/UseAPIApplication.java delete mode 100644 use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java diff --git a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java b/use-api/src/main/java/org/tzi/use/UseAPIApplication.java deleted file mode 100644 index f86920355..000000000 --- a/use-api/src/main/java/org/tzi/use/UseAPIApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.tzi.use; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -//localhost 8080 not in use anymore -@SpringBootApplication -public class UseAPIApplication { - public static void main(String[] args) { - SpringApplication.run(UseAPIApplication.class, args); - } - -// @Bean -// ApplicationRunner init(ClassRepo classRepo) { -// return args -> { -// Attribute name = new Attribute("name","String"); -// Operation operation = new Operation("operation()"); -// -// ClassDTO mclass2 = classRepo.save(new ClassDTO("TestClass2",name, operation)); -// -// -// }; -// } -} diff --git a/use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java b/use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java deleted file mode 100644 index 8b1378917..000000000 --- a/use-api/src/main/java/org/tzi/use/rest/exception/RestExceptionHandler.java +++ /dev/null @@ -1 +0,0 @@ - From 2e5b32928dd90aa97fb33cf8df1775420408895d Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 2 Dec 2025 15:41:36 +0100 Subject: [PATCH 110/148] better readability and cleaner code --- .../main/java/org/tzi/use/UseModelFacade.java | 125 +++++++++++------- 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index a616bf7f1..f0703cae3 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -1,8 +1,5 @@ package org.tzi.use; -import org.springframework.stereotype.Component; -import org.tzi.use.DTO.AssociationDTO; -import org.tzi.use.DTO.InvariantDTO; import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.entities.*; @@ -10,65 +7,37 @@ import java.util.HashMap; import java.util.Map; -@Component public class UseModelFacade { private final Map umaCache = new HashMap<>(); - private static String extractClassName(String concatedClassName) { - String[] parts = concatedClassName.split("::"); - return parts[0]; - } - - private UseModelApi getUMAfromModelNTT(ModelNTT modelNTT) throws UseApiException { - - if (umaCache.containsKey(modelNTT.getName())) return umaCache.get(modelNTT.getName()); - - UseModelApi result = new UseModelApi(modelNTT.getName()); - for (ClassNTT aClass : modelNTT.getClasses()) { - result.createClass(aClass.getName(), false); - for (AttributeNTT attribute : aClass.getAttributes()) { - result.createAttribute(aClass.getName(), attribute.getName(), attribute.getType()); - } - for (OperationNTT operation : aClass.getOperations()) { - result.createOperation(aClass.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); - } - } - for (Map.Entry ppcClass : modelNTT.getPrePostConditions().entrySet()) { - result.createPrePostCondition(extractClassName(ppcClass.getKey()), ppcClass.getValue().getOperationName(), ppcClass.getValue().getName(), ppcClass.getValue().getCondition(), ppcClass.getValue().isPre()); - } - - for (Map.Entry assocClass : modelNTT.getAssociations().entrySet()) { - result.createAssociation(assocClass.getValue().getAssociationName(), assocClass.getValue().getEnd1ClassName(), assocClass.getValue().getEnd1RoleName(), assocClass.getValue().getEnd1Multiplicity(), assocClass.getValue().getEnd1Aggregation().ordinal(), assocClass.getValue().getEnd2ClassName(), assocClass.getValue().getEnd2RoleName(), assocClass.getValue().getEnd2Multiplicity(), assocClass.getValue().getEnd2Aggregation().ordinal()); - } - - for (Map.Entry invariantClass : modelNTT.getInvariants().entrySet()) { - result.createInvariant(invariantClass.getValue().getInvName(), extractClassName(invariantClass.getKey()), invariantClass.getValue().getInvBody(), invariantClass.getValue().isExistential()); - } - - umaCache.put(modelNTT.getName(), result); - return result; - } - public void createModel(String modelName) { - //TOOD what do to when creating a new model? new UseModelApi().createModel(modelName); } - public void createClass(ModelNTT modelNTT, String className) throws UseApiException { UseModelApi uma = getUMAfromModelNTT(modelNTT); uma.createClass(className, false); } - public void createInvariant(InvariantDTO invariantDTOreq, String className, ModelNTT modelNTT) throws UseApiException { + public void createInvariant(ModelNTT modelNTT, InvariantNTT invariant, String className) throws UseApiException { UseModelApi uma = getUMAfromModelNTT(modelNTT); - uma.createInvariant(invariantDTOreq.getInvName(), className, invariantDTOreq.getInvBody(), invariantDTOreq.isExistential()); + uma.createInvariant(invariant.getInvName(), className, invariant.getInvBody(), invariant.isExistential()); } - public void createAssociation(AssociationDTO association, ModelNTT modelNTT) throws UseApiException { + public void createAssociation(ModelNTT modelNTT, AssociationNTT association) throws UseApiException { UseModelApi uma = getUMAfromModelNTT(modelNTT); - uma.createAssociation(association.getAssociationName(), association.getEnd1ClassName(), association.getEnd1RoleName(), association.getEnd1Multiplicity(), association.getEnd1Aggregation().ordinal(), association.getEnd2ClassName(), association.getEnd2RoleName(), association.getEnd2Multiplicity(), association.getEnd2Aggregation().ordinal()); + uma.createAssociation( + association.getAssociationName(), + association.getEnd1ClassName(), + association.getEnd1RoleName(), + association.getEnd1Multiplicity(), + association.getEnd1Aggregation().ordinal(), + association.getEnd2ClassName(), + association.getEnd2RoleName(), + association.getEnd2Multiplicity(), + association.getEnd2Aggregation().ordinal() + ); } public void createAttribute(ModelNTT modelNTT, String className, AttributeNTT attributeNTT) throws UseApiException { @@ -81,9 +50,73 @@ public void createOperation(ModelNTT modelNTT, String className, OperationNTT op uma.createOperation(className, operationNTT.getOperationName(), operationNTT.getParameter(), operationNTT.getReturnType()); } - public void createPrePostCondition(PrePostConditionNTT ppc, String className, ModelNTT modelNTT) throws UseApiException { + public void createPrePostCondition(ModelNTT modelNTT, PrePostConditionNTT ppc, String className) throws UseApiException { UseModelApi uma = getUMAfromModelNTT(modelNTT); uma.createPrePostCondition(className, ppc.getOperationName(), ppc.getName(), ppc.getCondition(), ppc.isPre()); } + + /* Helper Methods */ + + private static String extractClassName(String concatenatedClassName) { + String[] parts = concatenatedClassName.split("::"); + return parts[0]; + } + + private UseModelApi getUMAfromModelNTT(ModelNTT modelNTT) throws UseApiException { + UseModelApi cached = umaCache.get(modelNTT.getName()); + if (cached != null) { + return cached; + } + + UseModelApi result = new UseModelApi(modelNTT.getName()); + for (ClassNTT aClass : modelNTT.getClasses()) { + result.createClass(aClass.getName(), false); + for (AttributeNTT attribute : aClass.getAttributes()) { + result.createAttribute(aClass.getName(), attribute.getName(), attribute.getType()); + } + for (OperationNTT operation : aClass.getOperations()) { + result.createOperation(aClass.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); + } + } + for (Map.Entry ppcEntry : modelNTT.getPrePostConditions().entrySet()) { + PrePostConditionNTT ppc = ppcEntry.getValue(); + result.createPrePostCondition( + extractClassName(ppcEntry.getKey()), + ppc.getOperationName(), + ppc.getName(), + ppc.getCondition(), + ppc.isPre() + ); + } + + for (Map.Entry assocEntry : modelNTT.getAssociations().entrySet()) { + AssociationNTT association = assocEntry.getValue(); + result.createAssociation( + association.getAssociationName(), + association.getEnd1ClassName(), + association.getEnd1RoleName(), + association.getEnd1Multiplicity(), + association.getEnd1Aggregation().ordinal(), + association.getEnd2ClassName(), + association.getEnd2RoleName(), + association.getEnd2Multiplicity(), + association.getEnd2Aggregation().ordinal() + ); + } + + for (Map.Entry invariantEntry : modelNTT.getInvariants().entrySet()) { + InvariantNTT invariant = invariantEntry.getValue(); + result.createInvariant( + invariant.getInvName(), + extractClassName(invariantEntry.getKey()), + invariant.getInvBody(), + invariant.isExistential() + ); + } + + umaCache.put(modelNTT.getName(), result); + return result; + } + } From ccc8b9ead244fcd1be6e8c5ce4e65935c00eeb46 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 2 Dec 2025 16:04:34 +0100 Subject: [PATCH 111/148] Refactor UseModelFacade and ModelService method signatures Added @Component annotation to UseModelFacade for Spring integration. Updated method signatures in ModelService to consistently pass model and entity objects to UseModelFacade methods, improving clarity and maintainability. --- use-api/src/main/java/org/tzi/use/UseModelFacade.java | 2 ++ .../main/java/org/tzi/use/rest/services/ModelService.java | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index f0703cae3..627753c2f 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -1,5 +1,6 @@ package org.tzi.use; +import org.springframework.stereotype.Component; import org.tzi.use.api.UseApiException; import org.tzi.use.api.UseModelApi; import org.tzi.use.entities.*; @@ -7,6 +8,7 @@ import java.util.HashMap; import java.util.Map; +@Component public class UseModelFacade { private final Map umaCache = new HashMap<>(); diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index a578d46c7..698a1d2d0 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -122,7 +122,7 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr // find the class inside the model by className //TODO wenn die facade ein error bekommt wird die zeile darunter ausgeführt? - useModelFacade.createInvariant(invariantDTOreq, className, modelOfInvariant.get()); + useModelFacade.createInvariant(modelOfInvariant.get(),tmp_invariantntt, className); modelOfInvariant.get().getInvariants().put(className, tmp_invariantntt); //TODO modelRepo.save(modelOfInvariant.get()); @@ -132,7 +132,7 @@ public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOr public AssociationDTO createAssociation(String modelName, AssociationDTO association) throws UseApiException { AssociationNTT tmp_associationntt = associationMapperImpl.toEntity(association); Optional modelOfAssociation = modelRepo.findById(modelName); - useModelFacade.createAssociation(association, modelOfAssociation.get()); + useModelFacade.createAssociation( modelOfAssociation.get(),tmp_associationntt); modelOfAssociation.get().getAssociations().put(tmp_associationntt.getEnd2ClassName(),tmp_associationntt); modelOfAssociation.get().getAssociations().put(tmp_associationntt.getEnd1ClassName(), tmp_associationntt); modelRepo.save(modelOfAssociation.get()); @@ -142,7 +142,7 @@ public AssociationDTO createAssociation(String modelName, AssociationDTO associa public PrePostConditionDTO createPrePostCondition(String modelName, PrePostConditionDTO prePostConditionDTO, String className) throws UseApiException { PrePostConditionNTT tmp_prepostconditionntt = prePostConditionMapper.toEntity(prePostConditionDTO); Optional modelOfPrePostCondition = modelRepo.findById(modelName); - useModelFacade.createPrePostCondition(tmp_prepostconditionntt, className, modelOfPrePostCondition.get()); + useModelFacade.createPrePostCondition(modelOfPrePostCondition.get(),tmp_prepostconditionntt, className); String name = className + "::" + prePostConditionDTO.getOperationName() + prePostConditionDTO.getName(); From a3a8c534f23562f02d983c04dbcaba704ee6dcb5 Mon Sep 17 00:00:00 2001 From: husakki Date: Tue, 2 Dec 2025 21:10:10 +0100 Subject: [PATCH 112/148] Refactor ModelService for improved clarity and consistency Refactored ModelService to streamline method implementations, reduce code duplication, and improve naming consistency. Introduced helper method for model retrieval, replaced Optional usage with direct exception handling, and updated mappers to use interface-based injection. Simplified CRUD operations for models, classes, associations, invariants, and pre/post conditions. --- .../tzi/use/rest/services/ModelService.java | 184 ++++++++---------- 1 file changed, 84 insertions(+), 100 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 698a1d2d0..eac4adde4 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -11,7 +11,6 @@ import org.tzi.use.repository.ModelRepo; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor @@ -24,143 +23,128 @@ public class ModelService { private final AssociationMapperImpl associationMapperImpl; private final PrePostConditionMapper prePostConditionMapper; private final UseModelFacade useModelFacade; - - - /** - * Creates a new model with the given name - * - * @param modelDTOreq The DTO containing the model name and other properties - * @return The created model with assigned ID - * @throws UseApiException If there's an error creating the model - */ - public ModelDTO createModel(ModelDTO modelDTOreq) { - if (modelRepo.findById(modelDTOreq.getName()).isPresent()) { + private final InvariantMapper invariantMapper; + private final AssociationMapper associationMapper; + private final ClassMapper classMapper; + private final PrePostConditionMapperImpl prePostConditionMapperImpl; + + /* Create */ + public ModelDTO createModel(ModelDTO modelDTO) { + if (modelRepo.findById(modelDTO.getName()).isPresent()) { throw new DuplicateKeyException("Model name already exists"); } - ModelNTT tmp_modelntt = modelMapper.toEntity(modelDTOreq); + ModelNTT modelNTT = modelMapper.toEntity(modelDTO); - useModelFacade.createModel(tmp_modelntt.getName()); + useModelFacade.createModel(modelNTT.getName()); - modelRepo.save(tmp_modelntt); - return modelMapper.toDTO(tmp_modelntt); + modelRepo.save(modelNTT); + return modelMapper.toDTO(modelNTT); } - public ClassDTO createClass(String modelName, ClassDTO classDTOreq) throws UseApiException { - ClassNTT tmp_classntt = classMapperImpl.toEntity(classDTOreq); + public ClassDTO createClass(String modelName, ClassDTO classDTO) throws UseApiException { - ModelNTT modelOfClass = modelRepo.findById(modelName) - .orElseThrow(() -> new IllegalArgumentException("Model not found: " + modelName)); + ClassNTT classNTT = classMapper.toEntity(classDTO); - // Check if class already exists in this model - boolean classExists = modelOfClass.getClasses().stream() - .anyMatch(c -> c.getName().equals(classDTOreq.getName())); + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + + //TODO doesnt uma already throw an error if class exists? + boolean classExists = modelNTT.getClasses().stream().anyMatch(c -> c.getName().equals(classDTO.getName())); if (classExists) { throw new DuplicateKeyException("Class name already exists in model: " + modelName); } - // Create the class in the USE model - useModelFacade.createClass(modelOfClass, tmp_classntt.getName()); - modelOfClass.getClasses().add(tmp_classntt); + useModelFacade.createClass(modelNTT, classNTT.getName()); + modelNTT.getClasses().add(classNTT); + modelRepo.save(modelNTT); + + return classMapper.toDTO(classNTT); + } + + public PrePostConditionDTO createPrePostCondition(String modelName, PrePostConditionDTO prePostConditionDTO, String className) throws UseApiException { + PrePostConditionNTT prePostConditionNTT = prePostConditionMapper.toEntity(prePostConditionDTO); + ModelNTT modelNTT = findModelByNameOrThrow(modelName); - modelRepo.save(modelOfClass); - return classMapperImpl.toDTO(tmp_classntt); + useModelFacade.createPrePostCondition(modelNTT, prePostConditionNTT, className); + String name = className + "::" + prePostConditionDTO.getOperationName() + prePostConditionDTO.getName(); + modelNTT.getPrePostConditions().put(name, prePostConditionNTT); + modelRepo.save(modelNTT); + return prePostConditionMapper.toDTO(prePostConditionNTT); } - /** - * Retrieves a model by its ID - * - * @return The model DTO - * @throws UseApiException If the model is not found - */ - public ModelDTO getModelByName(String name) { - //isnt it a better practice to map it to a ntt first and then do the findBy? - Optional tmp_modelntt = modelRepo.findById(name); - return modelMapper.toDTO(tmp_modelntt.get()); + public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTO, String className) throws UseApiException { + InvariantNTT invariantNTT = invariantMapper.toEntity(invariantDTO); + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + + useModelFacade.createInvariant(modelNTT, invariantNTT, className); + modelNTT.getInvariants().put(className, invariantNTT); + modelRepo.save(modelNTT); + return invariantMapper.toDTO(invariantNTT); } - /** - * Retrieves all available models - * - * @return List of all model DTOs - */ - public List getAllModels() { - return modelRepo.findAll().stream().map(modelMapper::toDTO).toList(); + public AssociationDTO createAssociation(String modelName, AssociationDTO association) throws UseApiException { + AssociationNTT associationNTT = associationMapper.toEntity(association); + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + + useModelFacade.createAssociation(modelNTT, associationNTT); + modelNTT.getAssociations().put(associationNTT.getEnd1ClassName(), associationNTT); +// modelNTT.getAssociations().put(associationNTT.getEnd2ClassName(), associationNTT); + modelRepo.save(modelNTT); + return associationMapper.toDTO(associationNTT); } - public AssociationDTO getAssociationByName(String modelName, String associationName) { - return null; + /* Get */ + public ModelDTO getModelByName(String modelName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + return modelMapper.toDTO(modelNTT); } - public InvariantDTO getInvariantByName(String modelName, String invariantName) { - return null; + public List getAllModels() { + return modelRepo.findAll().stream().map(modelMapper::toDTO).toList(); } - public List getModelClasses(String modelName){ - Optional modelOpt = modelRepo.findById(modelName); - return modelOpt.get().getClasses().stream() - .map(classMapperImpl::toDTO) - .toList(); + + public List getModelClasses(String modelName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + return modelNTT.getClasses().stream().map(classMapperImpl::toDTO).toList(); } public List getModelAssociations(String modelName) { - Optional modelOpt = modelRepo.findById(modelName); -return modelOpt.get().getAssociations().values().stream().map(associationMapperImpl::toDTO).toList(); + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + return modelNTT.getAssociations().values().stream().map(associationMapperImpl::toDTO).toList(); } - public List getModelInvariants (String modelName) { - Optional modelOpt = modelRepo.findById(modelName); - return modelOpt.get().getInvariants().values().stream() - .map(invariantMapperImpl::toDTO) - .toList(); + public List getModelInvariants(String modelName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + return modelNTT.getInvariants().values().stream().map(invariantMapperImpl::toDTO).toList(); } - public InvariantDTO createInvariant(String modelName, InvariantDTO invariantDTOreq, String className) throws UseApiException { - InvariantNTT tmp_invariantntt = invariantMapperImpl.toEntity(invariantDTOreq); - - Optional modelOfInvariant = modelRepo.findById(modelName); - // find the class inside the model by className - - //TODO wenn die facade ein error bekommt wird die zeile darunter ausgeführt? - useModelFacade.createInvariant(modelOfInvariant.get(),tmp_invariantntt, className); - modelOfInvariant.get().getInvariants().put(className, tmp_invariantntt); - //TODO - modelRepo.save(modelOfInvariant.get()); - return invariantMapperImpl.toDTO(tmp_invariantntt); + public List getModelPrePostConditions(String modelName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + return modelNTT.getPrePostConditions().values().stream().map(prePostConditionMapperImpl::toDTO).toList(); } - public AssociationDTO createAssociation(String modelName, AssociationDTO association) throws UseApiException { - AssociationNTT tmp_associationntt = associationMapperImpl.toEntity(association); - Optional modelOfAssociation = modelRepo.findById(modelName); - useModelFacade.createAssociation( modelOfAssociation.get(),tmp_associationntt); - modelOfAssociation.get().getAssociations().put(tmp_associationntt.getEnd2ClassName(),tmp_associationntt); - modelOfAssociation.get().getAssociations().put(tmp_associationntt.getEnd1ClassName(), tmp_associationntt); - modelRepo.save(modelOfAssociation.get()); - return associationMapperImpl.toDTO(tmp_associationntt); + public AssociationDTO getAssociationByName(String modelName, String associationName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + AssociationNTT associationNTT = modelNTT.getAssociations().get(associationName); + return associationMapper.toDTO(associationNTT); } - public PrePostConditionDTO createPrePostCondition(String modelName, PrePostConditionDTO prePostConditionDTO, String className) throws UseApiException { - PrePostConditionNTT tmp_prepostconditionntt = prePostConditionMapper.toEntity(prePostConditionDTO); - Optional modelOfPrePostCondition = modelRepo.findById(modelName); - useModelFacade.createPrePostCondition(modelOfPrePostCondition.get(),tmp_prepostconditionntt, className); - String name = className + "::" + prePostConditionDTO.getOperationName() - + prePostConditionDTO.getName(); - - modelOfPrePostCondition.get().getPrePostConditions().put(name, tmp_prepostconditionntt); - modelRepo.save(modelOfPrePostCondition.get()); - return prePostConditionMapper.toDTO(tmp_prepostconditionntt); + public InvariantDTO getInvariantByName(String modelName, String invariantName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + InvariantNTT invariantNTT = modelNTT.getInvariants().get(invariantName); + return invariantMapper.toDTO(invariantNTT); } - public List getModelPrePostConditions(String modelName) { - Optional modelOpt = modelRepo.findById(modelName); - return modelOpt.get().getPrePostConditions().values().stream() - .map(prePostConditionMapper::toDTO) - .toList(); + public PrePostConditionDTO getPrePostConditionByName(String modelName, String prePostConditionName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + PrePostConditionNTT prePostConditionNTT = modelNTT.getPrePostConditions().get(prePostConditionName); + return prePostConditionMapper.toDTO(prePostConditionNTT); } - public PrePostConditionDTO getPrePostConditionByName(String modelName, String prePostConditionName) { - Optional modelOpt = modelRepo.findById(modelName); - PrePostConditionNTT prePostCondition = modelOpt.get().getPrePostConditions().get(prePostConditionName); - return prePostConditionMapper.toDTO(prePostCondition); + /* Helper Methods */ + private ModelNTT findModelByNameOrThrow(String modelName) { + return modelRepo.findById(modelName).orElseThrow(() -> new IllegalArgumentException("Model not found: " + modelName)); } + } From c1adfb628980de01cd59457fab57cd97a7bf56e2 Mon Sep 17 00:00:00 2001 From: husakki Date: Wed, 3 Dec 2025 00:31:12 +0100 Subject: [PATCH 113/148] ClassService overhaul cleanup and refactoring also made helper method in modelservice package private for usage inside classservice --- .../use/rest/controller/ClassController.java | 43 ++----- .../tzi/use/rest/services/ClassService.java | 119 +++++++----------- .../tzi/use/rest/services/ModelService.java | 2 +- 3 files changed, 55 insertions(+), 109 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index aa4e3faff..5ca3a37f9 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -31,7 +31,7 @@ public class ClassController { @GetMapping("/class/{className}") public ResponseEntity> getClassByName(@PathVariable String modelName, @PathVariable String className) { - ClassDTO classDTO = classService.getClassByName(className); + ClassDTO classDTO = classService.getClassByName(modelName, className); EntityModel entityModel = EntityModel.of(classDTO); entityModel.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withSelfRel()); entityModel.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withRel("attributes")); @@ -42,7 +42,7 @@ public ResponseEntity> getClassByName(@PathVariable String @GetMapping("/class/{className}/attributes") public ResponseEntity>> getAttributes(@PathVariable String modelName, @PathVariable String className) { - List attributes = classService.getAttributes(className); + List attributes = classService.getAttributes(modelName, className); List> attributeModels = attributes.stream() .map(attr -> EntityModel.of(attr, linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attr.getName())).withSelfRel())) @@ -56,7 +56,7 @@ public ResponseEntity>> getAttributes( @GetMapping("/class/{className}/attribute/{attributeName}") public ResponseEntity> getAttributeByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String attributeName) { // Assuming ClassService has a method to get a single attribute by name - AttributeDTO attribute = classService.getAttributeByName(className, attributeName); + AttributeDTO attribute = classService.getAttributeByName(modelName, className, attributeName); EntityModel entityModel = EntityModel.of(attribute); entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attributeName)).withSelfRel()); return ResponseEntity.ok(entityModel); @@ -65,7 +65,7 @@ public ResponseEntity> getAttributeByName(@PathVariabl @GetMapping("/class/{className}/operations") public ResponseEntity>> getOperations(@PathVariable String modelName, @PathVariable String className) { - List operations = classService.getOperations(className); + List operations = classService.getOperations(modelName, className); List> operationModels = operations.stream() .map(op -> EntityModel.of(op, linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, op.getOperationName())).withSelfRel())) @@ -79,38 +79,17 @@ public ResponseEntity>> getOperations( @GetMapping("/class/{className}/operation/{operationName}") public ResponseEntity> getOperationByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String operationName) { // Assuming ClassService has a method to get a single operation by name - OperationDTO operation = classService.getOperationByName(className, operationName); + OperationDTO operation = classService.getOperationByName(modelName, className, operationName); EntityModel entityModel = EntityModel.of(operation); entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, operationName)).withSelfRel()); return ResponseEntity.ok(entityModel); } -// @GetMapping("/class/{className}/preposts") -// public ResponseEntity>> getPrePostConditions(@PathVariable String modelName, @PathVariable String className) { -// List conditions = classService.getPrePostConditions(className); -// List> conditionModels = conditions.stream() -// .map(cond -> EntityModel.of(cond, -// linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, cond.getName())).withSelfRel())) -// .collect(Collectors.toList()); -// -// CollectionModel> collectionModel = CollectionModel.of(conditionModels); -// collectionModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withSelfRel()); -// return ResponseEntity.ok(collectionModel); -// } - -// @GetMapping("/class/{className}/prepost/{conditionName}") -// public ResponseEntity> getPrePostConditionByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String conditionName) { -// // Assuming ClassService has a method to get a single pre/post condition by name -// PrePostConditionDTO condition = classService.getPrePostConditionByName(className, conditionName); -// EntityModel entityModel = EntityModel.of(condition); -// entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, conditionName)).withSelfRel()); -// return ResponseEntity.ok(entityModel); -// } @PostMapping("/class/{className}/attribute") public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) throws UseApiException { - AttributeDTO newAttribute = classService.createAttribute(className, attributeDTO); + AttributeDTO newAttribute = classService.createAttribute(modelName, className, attributeDTO); EntityModel entityModel = EntityModel.of(newAttribute); entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, newAttribute.getName())).withSelfRel()); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); @@ -118,17 +97,9 @@ public ResponseEntity> addAttribute(@PathVariable Stri @PostMapping("/class/{className}/operation") public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) throws UseApiException { - OperationDTO newOperation = classService.createOperation(className, operationDTO); + OperationDTO newOperation = classService.createOperation(modelName, className, operationDTO); EntityModel entityModel = EntityModel.of(newOperation); entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, newOperation.getOperationName())).withSelfRel()); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } - -// @PostMapping("/class/{className}/prepost") -// public ResponseEntity> addPrePostCondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) { -// PrePostConditionDTO newCondition = classService.addPrePostCondition(className, prePostConditionDTO); -// EntityModel entityModel = EntityModel.of(newCondition); -// entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditionByName(modelName, className, newCondition.getName())).withSelfRel()); -// return new ResponseEntity<>(entityModel, HttpStatus.CREATED); -// } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index f1d836ca4..f4a912857 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -23,97 +23,72 @@ public class ClassService { private final ClassMapper classMapper; private final AttributeMapper attributeMapper; private final OperationMapper operationMapper; - private final PrePostConditionMapper prePostConditionMapper; private final UseModelFacade useModelFacade; + private final ModelService modelService; - public ClassDTO getClassByName(String className) { - ModelNTT model = modelRepo.findByClassesName(className) - .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); - ClassNTT classNTT = model.getClasses().stream() - .filter(c -> c.getName().equals(className)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - return classMapper.toDTO(classNTT); - } - - public List getAttributes(String className) { - ModelNTT model = modelRepo.findByClassesName(className) - .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); - ClassNTT classNTT = model.getClasses().stream() - .filter(c -> c.getName().equals(className)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - return classNTT.getAttributes().stream().map(attributeMapper::toDTO).toList(); - } - - public List getOperations(String className) { - ModelNTT model = modelRepo.findByClassesName(className) - .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); - ClassNTT classNTT = model.getClasses().stream() - .filter(c -> c.getName().equals(className)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - return classNTT.getOperations().stream().map(operationMapper::toDTO).toList(); - } - -// public List getPrePostConditions(String className) { -// Optional classNTTOpt = classRepo.findById(className); -// return classNTTOpt.get().getPrePostCond().stream().map(prePostConditionMapper::toDTO).toList(); -// } - - public AttributeDTO createAttribute(String className, AttributeDTO attributeDTO) throws UseApiException { + /* Create */ + public AttributeDTO createAttribute(String modelName, String className, AttributeDTO attributeDTO) throws UseApiException { AttributeNTT attributeNTT = attributeMapper.toEntity(attributeDTO); + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); - // Find model containing this class - ModelNTT model = modelRepo.findByClassesName(className) - .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); - ClassNTT classNTT = model.getClasses().stream() - .filter(c -> c.getName().equals(className)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - - // Create attribute in USE model - useModelFacade.createAttribute(model, className, attributeNTT); + useModelFacade.createAttribute(modelNTT, className, attributeNTT); - // Add to entity and save through model classNTT.getAttributes().add(attributeNTT); - modelRepo.save(model); + modelRepo.save(modelNTT); return attributeMapper.toDTO(attributeNTT); } - public OperationDTO createOperation(String className, OperationDTO operationDTO) throws UseApiException { + public OperationDTO createOperation(String modelName, String className, OperationDTO operationDTO) throws UseApiException { OperationNTT operationNTT = operationMapper.toEntity(operationDTO); + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); - // Find model containing this class - ModelNTT model = modelRepo.findByClassesName(className) - .orElseThrow(() -> new IllegalArgumentException("Model not found for class: " + className)); - ClassNTT classNTT = model.getClasses().stream() - .filter(c -> c.getName().equals(className)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); - - // Create operation in USE model - useModelFacade.createOperation(model, className, operationNTT); + useModelFacade.createOperation(modelNTT, className, operationNTT); - // Add to entity and save through model classNTT.getOperations().add(operationNTT); - modelRepo.save(model); + modelRepo.save(modelNTT); return operationMapper.toDTO(operationNTT); } -// public PrePostConditionDTO addPrePostCondition(String className, PrePostConditionDTO prePostCondition) { -// return null; -// } + /* Get */ + public ClassDTO getClassByName(String modelName, String className) { + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); + return classMapper.toDTO(classNTT); + } + + public List getAttributes(String modelName, String className) { + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); + return classNTT.getAttributes().stream().map(attributeMapper::toDTO).toList(); + } + + public List getOperations(String modelName, String className) { + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); + return classNTT.getOperations().stream().map(operationMapper::toDTO).toList(); + } -// public PrePostConditionDTO getPrePostConditionByName(String className, String conditionName) { -// return null; -// } + public OperationDTO getOperationByName(String modelName, String className, String operationName) { + return getOperations(modelName,className).stream() + .filter(op -> op.getOperationName().equals(operationName)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Operation not found: " + operationName)); + } - public OperationDTO getOperationByName(String className, String operationName) { - return null; + public AttributeDTO getAttributeByName(String modelName, String className, String attributeName) { + return getAttributes(modelName, className).stream() + .filter(attr -> attr.getName().equals(attributeName)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Attribute not found: " + attributeName)); } - public AttributeDTO getAttributeByName(String className, String attributeName) { - return null; + /* Helper Methods */ + private ClassNTT findClassByNameOrThrow(ModelNTT modelNTT, String className) { + return modelNTT.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index eac4adde4..ec1d83ce7 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -143,7 +143,7 @@ public PrePostConditionDTO getPrePostConditionByName(String modelName, String pr } /* Helper Methods */ - private ModelNTT findModelByNameOrThrow(String modelName) { + ModelNTT findModelByNameOrThrow(String modelName) { return modelRepo.findById(modelName).orElseThrow(() -> new IllegalArgumentException("Model not found: " + modelName)); } From 7ea539201dde698dc4609f6d9ae20f3abc18148d Mon Sep 17 00:00:00 2001 From: husakki Date: Wed, 3 Dec 2025 01:13:45 +0100 Subject: [PATCH 114/148] sorting methodes and improving HATEOAS --- .../use/rest/controller/ModelController.java | 300 +++++++++--------- .../tzi/use/rest/services/ModelService.java | 1 - 2 files changed, 144 insertions(+), 157 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 7030abceb..aa9fc26b1 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -26,60 +26,28 @@ public class ModelController { // and Spring will use that constructor for dependency injection private final ModelService modelService; - /** - * Create a new model - * - * @param modelDTO The model data to create - * @return The created model with HATEOAS links - */ - @PostMapping("/model") - public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { - ModelDTO createdModel = modelService.createModel(modelDTO); - - // Create an EntityModel (HATEOAS) with the response - EntityModel entityModel = EntityModel.of(createdModel); - - // Add HATEOAS links - // Link to self - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(createdModel.getName())).withSelfRel()); - - // Link to get all classes in this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(createdModel.getName())).withRel("classes")); - - // Link to get all associations in this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(createdModel.getName())).withRel("associations")); - - // Link to get all invariants in this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(createdModel.getName())).withRel("invariants")); - - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); - } + // ======================================== + // GET Mappings + // ======================================== /** * Retrieve a model by its ID * - * @param name The ID of the model to retrieve + * @param modelName The ID of the model to retrieve * @return The model with HATEOAS links */ - @GetMapping("/model/{name}") - public ResponseEntity> getModelByName(@PathVariable String name) { - ModelDTO model = modelService.getModelByName(name); + @GetMapping("/model/{modelName}") + public ResponseEntity> getModelByName(@PathVariable String modelName) { + ModelDTO modelDTO = modelService.getModelByName(modelName); - // Create an EntityModel (HATEOAS) with the response - EntityModel entityModel = EntityModel.of(model); - - // Add HATEOAS links - // Link to self - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(name)).withSelfRel()); + EntityModel entityModel = EntityModel.of(modelDTO); - // Link to get all classes in this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(name)).withRel("classes")); - - // Link to get all associations in this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(name)).withRel("associations")); - - // Link to get all invariants in this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(name)).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getAllModels()).withRel("models")); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withRel("prePostConditions")); return new ResponseEntity<>(entityModel, HttpStatus.OK); } @@ -119,13 +87,13 @@ public ResponseEntity>> getAllModels() { entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(model.getName())).withSelfRel()); // Add classes link - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(model.getName())).withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(model.getName())).withRel("classes")); // Add associations link - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(model.getName())).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(model.getName())).withRel("associations")); // Add invariants link - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(model.getName())).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(model.getName())).withRel("invariants")); return entityModel; @@ -144,36 +112,11 @@ public ResponseEntity>> getAllModels() { return new ResponseEntity<>(collectionModel, HttpStatus.OK); } - @PostMapping("/model/{modelName}/class") - public ResponseEntity> createClass(@PathVariable String modelName, @RequestBody ClassDTO classDTO) throws UseApiException { - ClassDTO createdClass = modelService.createClass(modelName, classDTO); - - // Wrap the created class in an EntityModel for HATEOAS - EntityModel entityModel = EntityModel.of(createdClass); - - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - - // Link to the classes listing for this model (also used as self since there's no single-class GET) - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); - - // Link to create another class in this model - entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("class").withRel("create-class")); - - // Link to associations for this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); - - // Link to invariants for this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withRel("invariants")); - - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); - } - /** * Placeholder method to retrieve all classes in a model */ @GetMapping("/model/{modelName}/classes") - public ResponseEntity getModelClasses(@PathVariable String modelName) { + public ResponseEntity getClasses(@PathVariable String modelName) { List modelClasses = modelService.getModelClasses(modelName); // Convert each class to an EntityModel with links @@ -184,7 +127,7 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); // Link to this classes collection (self) - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); // Link to create another class try { @@ -194,10 +137,10 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { } // Link to associations - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); // Link to invariants - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); return entityModel; }).collect(Collectors.toList()); @@ -206,7 +149,7 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { CollectionModel> collectionModel = CollectionModel.of(classEntities); // Add self-link to the collection - collectionModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); // Add link to create a new class try { @@ -223,7 +166,7 @@ public ResponseEntity getModelClasses(@PathVariable String modelName) { * Placeholder method to retrieve all associations in a model */ @GetMapping("/model/{modelName}/associations") - public ResponseEntity>> getModelAssociations(@PathVariable String modelName) { + public ResponseEntity>> getAssociations(@PathVariable String modelName) { List associations = modelService.getModelAssociations(modelName); List> associationEntities = associations.stream().map(association -> { @@ -235,23 +178,11 @@ public ResponseEntity>> getModelAsso CollectionModel> collectionModel = CollectionModel.of(associationEntities); - collectionModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withSelfRel()); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } - @PostMapping("/model/{modelName}/association") - public ResponseEntity> createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) throws UseApiException { - AssociationDTO createdAssociation = modelService.createAssociation(modelName, association); - - EntityModel entityModel = EntityModel.of(createdAssociation); - - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, createdAssociation.getAssociationName())).withSelfRel()); - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); - } - /** * Retrieve all invariants in a model. * @@ -259,7 +190,7 @@ public ResponseEntity> createAssociation(@PathVariab * @return A collection of invariants with HATEOAS links. */ @GetMapping("/model/{modelName}/invariants") - public ResponseEntity>> getModelInvariants(@PathVariable String modelName) { + public ResponseEntity>> getInvariants(@PathVariable String modelName) { List invariants = modelService.getModelInvariants(modelName); List> invariantEntities = invariants.stream().map(invariant -> { @@ -269,13 +200,13 @@ public ResponseEntity>> getModelInvari entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); // Self-link to this collection - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withSelfRel()); // Link to classes - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); // Link to associations - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); return entityModel; }).collect(Collectors.toList()); @@ -283,11 +214,120 @@ public ResponseEntity>> getModelInvari CollectionModel> collectionModel = CollectionModel.of(invariantEntities); // Self-link for the collection - collectionModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withSelfRel()); + + return new ResponseEntity<>(collectionModel, HttpStatus.OK); + } + + @GetMapping("/model/{modelName}/prepostconditions") + public ResponseEntity>> getPrePostConditions(@PathVariable String modelName) { + List prePostConditions = modelService.getModelPrePostConditions(modelName); + + List> prePostConditionEntities = prePostConditions.stream().map(prePostCondition -> { + EntityModel entityModel = EntityModel.of(prePostCondition); + + // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + // Self-link to this collection + entityModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withSelfRel()); + + // Link to classes + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); + + // Link to associations + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + + return entityModel; + }).collect(Collectors.toList()); + + CollectionModel> collectionModel = CollectionModel.of(prePostConditionEntities); + + // Self-link for the collection + collectionModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withSelfRel()); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } + @GetMapping("/model/{modelName}/prepostcondition/{prePostConditionName}") + public ResponseEntity> getModelPrePostCondByName(@PathVariable String modelName, @PathVariable String prePostConditionName) { + PrePostConditionDTO prePostCondition = modelService.getPrePostConditionByName(modelName, prePostConditionName); + EntityModel entityModel = EntityModel.of(prePostCondition); + entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCondByName(modelName, prePostConditionName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); + } + + // ======================================== + // POST Mappings + // ======================================== + + /** + * Create a new model + * + * @param modelDTO The model data to create + * @return The created model with HATEOAS links + */ + @PostMapping("/model") + public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { + ModelDTO createdModel = modelService.createModel(modelDTO); + + // Create an EntityModel (HATEOAS) with the response + EntityModel entityModel = EntityModel.of(createdModel); + + // Add HATEOAS links + // Link to self + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(createdModel.getName())).withSelfRel()); + + // Link to get all classes in this model + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(createdModel.getName())).withRel("classes")); + + // Link to get all associations in this model + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(createdModel.getName())).withRel("associations")); + + // Link to get all invariants in this model + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(createdModel.getName())).withRel("invariants")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + + @PostMapping("/model/{modelName}/class") + public ResponseEntity> createClass(@PathVariable String modelName, @RequestBody ClassDTO classDTO) throws UseApiException { + ClassDTO createdClass = modelService.createClass(modelName, classDTO); + + // Wrap the created class in an EntityModel for HATEOAS + EntityModel entityModel = EntityModel.of(createdClass); + + // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + // Link to the classes listing for this model (also used as self since there's no single-class GET) + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); + + // Link to create another class in this model + entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("class").withRel("create-class")); + + // Link to associations for this model + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + + // Link to invariants for this model + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + + @PostMapping("/model/{modelName}/association") + public ResponseEntity> createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) throws UseApiException { + AssociationDTO createdAssociation = modelService.createAssociation(modelName, association); + + EntityModel entityModel = EntityModel.of(createdAssociation); + + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, createdAssociation.getAssociationName())).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + + return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + } + @PostMapping("/model/{modelName}/{className}/invariant") public ResponseEntity> createInvariant(@PathVariable String modelName, @PathVariable String className, @RequestBody InvariantDTO invariantDTO) throws UseApiException { InvariantDTO createdInvariant = modelService.createInvariant(modelName, invariantDTO, className); @@ -299,16 +339,16 @@ public ResponseEntity> createInvariant(@PathVariable S entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); // Link to the invariants listing for this model (also used as self since there's no single-invariant GET) - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withSelfRel()); // Link to create another invariant in this model entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("invariant").withRel("create-invariant")); // Link to classes for this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); // Link to associations for this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @@ -324,69 +364,17 @@ public ResponseEntity> createprepostcondition(@ entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); // Link to the classes listing for this model (also used as self since there's no single-prepostcondition GET) - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); // Link to create another pre/post condition in this model entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("prepostcondition").withRel("create-prepostcondition")); // Link to invariants for this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariants(modelName)).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); // Link to associations for this model - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } - - @GetMapping("/model/{modelName}/prepostconditions") - public ResponseEntity>> getModelPrePostCond(@PathVariable String modelName) { - List prePostConditions = modelService.getModelPrePostConditions(modelName); - - List> prePostConditionEntities = prePostConditions.stream().map(prePostCondition -> { - EntityModel entityModel = EntityModel.of(prePostCondition); - - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - - // Self-link to this collection - entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCond(modelName)).withSelfRel()); - - // Link to classes - entityModel.add(linkTo(methodOn(ModelController.class).getModelClasses(modelName)).withRel("classes")); - - // Link to associations - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociations(modelName)).withRel("associations")); - - return entityModel; - }).collect(Collectors.toList()); - - CollectionModel> collectionModel = CollectionModel.of(prePostConditionEntities); - - // Self-link for the collection - collectionModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCond(modelName)).withSelfRel()); - - return new ResponseEntity<>(collectionModel, HttpStatus.OK); - } - - @GetMapping("/model/{modelName}/prepostcondition/{prePostConditionName}") - public ResponseEntity> getModelPrePostCondByName(@PathVariable String modelName, @PathVariable String prePostConditionName) { - PrePostConditionDTO prePostCondition = modelService.getPrePostConditionByName(modelName, prePostConditionName); - EntityModel entityModel = EntityModel.of(prePostCondition); - entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCondByName(modelName, prePostConditionName)).withSelfRel()); - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - return new ResponseEntity<>(entityModel, HttpStatus.OK); - } - - - /* - Endpoints that are needed (prefix /api): - POST /model - Create a new model :check: - POST /model/class - Add a new class to a model - POST /model/association - Add a new association to a model - POST /model/invariant - Add a new invariant to a model - GET /model/{id} - Retrieve a model by ID - GET /model/{id}/classes - Retrieve all classes in a model - GET /model/{id}/associations - Retrieve all association in a model - GET /model/{id}/invariants - Retrieve all invariants in a model - */ } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index ec1d83ce7..dc41215e7 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -88,7 +88,6 @@ public AssociationDTO createAssociation(String modelName, AssociationDTO associa useModelFacade.createAssociation(modelNTT, associationNTT); modelNTT.getAssociations().put(associationNTT.getEnd1ClassName(), associationNTT); -// modelNTT.getAssociations().put(associationNTT.getEnd2ClassName(), associationNTT); modelRepo.save(modelNTT); return associationMapper.toDTO(associationNTT); } From f1c92be4cc79c4b83885de4067a9596b0583b73f Mon Sep 17 00:00:00 2001 From: husakki Date: Wed, 3 Dec 2025 16:05:51 +0100 Subject: [PATCH 115/148] get endpoints better hateoas --- .../use/rest/controller/ModelController.java | 184 +++++++----------- 1 file changed, 68 insertions(+), 116 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index aa9fc26b1..0bad5846e 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -10,8 +10,8 @@ import org.tzi.use.api.UseApiException; import org.tzi.use.rest.services.ModelService; +import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; @@ -37,13 +37,12 @@ public class ModelController { * @return The model with HATEOAS links */ @GetMapping("/model/{modelName}") - public ResponseEntity> getModelByName(@PathVariable String modelName) { + public ResponseEntity> getModelByName(@PathVariable String modelName) throws UseApiException { ModelDTO modelDTO = modelService.getModelByName(modelName); EntityModel entityModel = EntityModel.of(modelDTO); entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withSelfRel()); - entityModel.add(linkTo(methodOn(ModelController.class).getAllModels()).withRel("models")); entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); @@ -53,110 +52,73 @@ public ResponseEntity> getModelByName(@PathVariable String } @GetMapping("/model/{modelName}/association/{associationName}") - public ResponseEntity> getModelAssociationByName(@PathVariable String modelName, @PathVariable String associationName) { + public ResponseEntity> getModelAssociationByName(@PathVariable String modelName, @PathVariable String associationName) throws UseApiException { AssociationDTO association = modelService.getAssociationByName(modelName, associationName); + EntityModel entityModel = EntityModel.of(association); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, associationName)).withSelfRel()); entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); } @GetMapping("/model/{modelName}/invariant/{invariantName}") - public ResponseEntity> getModelInvariantByName(@PathVariable String modelName, @PathVariable String invariantName) { + public ResponseEntity> getModelInvariantByName(@PathVariable String modelName, @PathVariable String invariantName) throws UseApiException { InvariantDTO invariant = modelService.getInvariantByName(modelName, invariantName); + EntityModel entityModel = EntityModel.of(invariant); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariantByName(modelName, invariantName)).withSelfRel()); entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); } - /** - * Retrieve all models - * - * @return List of all models with HATEOAS links - */ @GetMapping("/models") - public ResponseEntity>> getAllModels() { + public ResponseEntity>> getAllModels() throws UseApiException { List models = modelService.getAllModels(); - // Convert each model to an EntityModel with links - List> modelEntities = models.stream().map(model -> { - EntityModel entityModel = EntityModel.of(model); - - // Add self link - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(model.getName())).withSelfRel()); + List> modelEntities = new ArrayList<>(); + for (ModelDTO modelDTO : models) { + EntityModel entityModel = EntityModel.of(modelDTO); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelDTO.getName())).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelDTO.getName())).withRel("classes")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelDTO.getName())).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelDTO.getName())).withRel("invariants")); - // Add classes link - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(model.getName())).withRel("classes")); - - // Add associations link - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(model.getName())).withRel("associations")); - - // Add invariants link - entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(model.getName())).withRel("invariants")); - - - return entityModel; - }).collect(Collectors.toList()); + modelEntities.add(entityModel); + } - // Create a CollectionModel (container of EntityModels) CollectionModel> collectionModel = CollectionModel.of(modelEntities); - - // Add link to this collection collectionModel.add(linkTo(methodOn(ModelController.class).getAllModels()).withSelfRel()); - - // Add link to create a new model - collectionModel.add(linkTo(methodOn(ModelController.class).createModel(null)).withRel("create-model")); + collectionModel.add(linkTo(methodOn(ModelController.class).createModel(null)).withRel("create model")); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } - /** - * Placeholder method to retrieve all classes in a model - */ + @GetMapping("/model/{modelName}/classes") - public ResponseEntity getClasses(@PathVariable String modelName) { + public ResponseEntity getClasses(@PathVariable String modelName) throws UseApiException { List modelClasses = modelService.getModelClasses(modelName); - // Convert each class to an EntityModel with links - List> classEntities = modelClasses.stream().map(classDTO -> { - EntityModel entityModel = EntityModel.of(classDTO); - - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + List> classEntities = new ArrayList<>(); + for (ClassDTO classOfModelName : modelClasses) { + EntityModel entityModel = EntityModel.of(classOfModelName); - // Link to this classes collection (self) entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); + entityModel.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, null)).withRel("class by name")); - // Link to create another class - try { - entityModel.add(linkTo(methodOn(ModelController.class).createClass(modelName, null)).withRel("create-class")); - } catch (UseApiException e) { - throw new RuntimeException(e); - } - - // Link to associations - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); - - // Link to invariants - entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); - - return entityModel; - }).collect(Collectors.toList()); + classEntities.add(entityModel); + } - // Create a CollectionModel CollectionModel> collectionModel = CollectionModel.of(classEntities); - - // Add self-link to the collection collectionModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); - - // Add link to create a new class - try { - collectionModel.add(linkTo(methodOn(ModelController.class).createClass(modelName, null)).withRel("create-class")); - } catch (UseApiException e) { - throw new RuntimeException(e); - } + collectionModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + collectionModel.add(linkTo(methodOn(ModelController.class).createClass(modelName, null)).withRel("create class")); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @@ -166,95 +128,85 @@ public ResponseEntity getClasses(@PathVariable String modelName) { * Placeholder method to retrieve all associations in a model */ @GetMapping("/model/{modelName}/associations") - public ResponseEntity>> getAssociations(@PathVariable String modelName) { + public ResponseEntity>> getAssociations(@PathVariable String modelName) throws UseApiException { List associations = modelService.getModelAssociations(modelName); - List> associationEntities = associations.stream().map(association -> { - EntityModel entityModel = EntityModel.of(association); - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, association.getAssociationName())).withSelfRel()); - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - return entityModel; - }).collect(Collectors.toList()); + List> associationEntities = new ArrayList<>(); + for (AssociationDTO associationDTO : associations) { + EntityModel entityModel = EntityModel.of(associationDTO); + + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, associationDTO.getAssociationName())).withSelfRel()); + associationEntities.add(entityModel); + } CollectionModel> collectionModel = CollectionModel.of(associationEntities); collectionModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + collectionModel.add(linkTo(methodOn(ModelController.class).createAssociation(modelName, null)).withRel("create association")); + return new ResponseEntity<>(collectionModel, HttpStatus.OK); } - /** - * Retrieve all invariants in a model. - * - * @param modelName The name of the model. - * @return A collection of invariants with HATEOAS links. - */ + @GetMapping("/model/{modelName}/invariants") - public ResponseEntity>> getInvariants(@PathVariable String modelName) { + public ResponseEntity>> getInvariants(@PathVariable String modelName) throws UseApiException { List invariants = modelService.getModelInvariants(modelName); - List> invariantEntities = invariants.stream().map(invariant -> { - EntityModel entityModel = EntityModel.of(invariant); - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + List> invariantEntities = new ArrayList<>(); + for (InvariantDTO invariantDTO : invariants) { + EntityModel entityModel = EntityModel.of(invariantDTO); - // Self-link to this collection entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withSelfRel()); - // Link to classes - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); - - // Link to associations - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); - - return entityModel; - }).collect(Collectors.toList()); + invariantEntities.add(entityModel); + } CollectionModel> collectionModel = CollectionModel.of(invariantEntities); - // Self-link for the collection collectionModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + collectionModel.add(linkTo(methodOn(ModelController.class).createInvariant(modelName,null,null)).withRel("create invariant")); + return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @GetMapping("/model/{modelName}/prepostconditions") - public ResponseEntity>> getPrePostConditions(@PathVariable String modelName) { + public ResponseEntity>> getPrePostConditions(@PathVariable String modelName) throws UseApiException { List prePostConditions = modelService.getModelPrePostConditions(modelName); - List> prePostConditionEntities = prePostConditions.stream().map(prePostCondition -> { - EntityModel entityModel = EntityModel.of(prePostCondition); - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + List> prePostConditionEntities = new ArrayList<>(); + for (PrePostConditionDTO prePostConditionDTO : prePostConditions) { + EntityModel entityModel = EntityModel.of(prePostConditionDTO); - // Self-link to this collection entityModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withSelfRel()); - // Link to classes - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); - - // Link to associations - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); - - return entityModel; - }).collect(Collectors.toList()); + prePostConditionEntities.add(entityModel); + } CollectionModel> collectionModel = CollectionModel.of(prePostConditionEntities); - // Self-link for the collection collectionModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + collectionModel.add(linkTo(methodOn(ModelController.class).createprepostcondition(modelName,null,null)).withRel("create prepostcondition")); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @GetMapping("/model/{modelName}/prepostcondition/{prePostConditionName}") - public ResponseEntity> getModelPrePostCondByName(@PathVariable String modelName, @PathVariable String prePostConditionName) { + public ResponseEntity> getModelPrePostCondByName(@PathVariable String modelName, @PathVariable String prePostConditionName) throws UseApiException { PrePostConditionDTO prePostCondition = modelService.getPrePostConditionByName(modelName, prePostConditionName); + EntityModel entityModel = EntityModel.of(prePostCondition); + entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCondByName(modelName, prePostConditionName)).withSelfRel()); entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withRel("prePostConditions")); + return new ResponseEntity<>(entityModel, HttpStatus.OK); } @@ -269,7 +221,7 @@ public ResponseEntity> getModelPrePostCondByNam * @return The created model with HATEOAS links */ @PostMapping("/model") - public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) { + public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) throws UseApiException { ModelDTO createdModel = modelService.createModel(modelDTO); // Create an EntityModel (HATEOAS) with the response From 86c395f3f9c76915e4313c2510c2439b065c21ec Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 4 Dec 2025 22:56:43 +0100 Subject: [PATCH 116/148] HATEOAS improved --- .../use/rest/controller/ClassController.java | 116 +++++++++++------- .../use/rest/controller/ModelController.java | 86 ++++--------- 2 files changed, 101 insertions(+), 101 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 5ca3a37f9..2a49a2669 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -17,6 +17,7 @@ import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.CollectionModel; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -30,59 +31,84 @@ public class ClassController { private final ClassService classService; @GetMapping("/class/{className}") - public ResponseEntity> getClassByName(@PathVariable String modelName, @PathVariable String className) { + public ResponseEntity> getClassByName(@PathVariable String modelName, @PathVariable String className) throws UseApiException { ClassDTO classDTO = classService.getClassByName(modelName, className); - EntityModel entityModel = EntityModel.of(classDTO); - entityModel.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withSelfRel()); - entityModel.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withRel("attributes")); - entityModel.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withRel("operations")); -// entityModel.add(linkTo(methodOn(ClassController.class).getPrePostConditions(modelName, className)).withRel("preposts")); - return ResponseEntity.ok(entityModel); + + EntityModel entityModels = EntityModel.of(classDTO); + + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withRel("attributes")); + entityModels.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withRel("operations")); + entityModels.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); + + return ResponseEntity.ok(entityModels); } @GetMapping("/class/{className}/attributes") - public ResponseEntity>> getAttributes(@PathVariable String modelName, @PathVariable String className) { + public ResponseEntity>> getAttributes(@PathVariable String modelName, @PathVariable String className) throws UseApiException { List attributes = classService.getAttributes(modelName, className); - List> attributeModels = attributes.stream() - .map(attr -> EntityModel.of(attr, - linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attr.getName())).withSelfRel())) - .collect(Collectors.toList()); - - CollectionModel> collectionModel = CollectionModel.of(attributeModels); - collectionModel.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withSelfRel()); - return ResponseEntity.ok(collectionModel); + List> attributeModels = new ArrayList<>(); + for (AttributeDTO attr : attributes) { + EntityModel attributeDTOEntityModel = EntityModel.of(attr); + + attributeDTOEntityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attr.getName())).withSelfRel()); + + attributeModels.add(attributeDTOEntityModel); + } + + CollectionModel> entityModels = CollectionModel.of(attributeModels); + entityModels.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withRel("class")); + + return ResponseEntity.ok(entityModels); } @GetMapping("/class/{className}/attribute/{attributeName}") - public ResponseEntity> getAttributeByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String attributeName) { - // Assuming ClassService has a method to get a single attribute by name + public ResponseEntity> getAttributeByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String attributeName) throws UseApiException { AttributeDTO attribute = classService.getAttributeByName(modelName, className, attributeName); - EntityModel entityModel = EntityModel.of(attribute); - entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attributeName)).withSelfRel()); - return ResponseEntity.ok(entityModel); + + EntityModel entityModels = EntityModel.of(attribute); + + entityModels.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, attributeName)).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getAttributes(modelName, className)).withRel("attributes")); + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withRel("class")); + + return ResponseEntity.ok(entityModels); } @GetMapping("/class/{className}/operations") - public ResponseEntity>> getOperations(@PathVariable String modelName, @PathVariable String className) { + public ResponseEntity>> getOperations(@PathVariable String modelName, @PathVariable String className) throws UseApiException { List operations = classService.getOperations(modelName, className); - List> operationModels = operations.stream() - .map(op -> EntityModel.of(op, - linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, op.getOperationName())).withSelfRel())) - .collect(Collectors.toList()); - - CollectionModel> collectionModel = CollectionModel.of(operationModels); - collectionModel.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withSelfRel()); - return ResponseEntity.ok(collectionModel); + List> operationModels = new ArrayList<>(); + for (OperationDTO op : operations) { + EntityModel operationDTOEntityModel = EntityModel.of(op); + + operationDTOEntityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, op.getOperationName())).withSelfRel()); + + operationModels.add(operationDTOEntityModel); + } + + CollectionModel> entityModels = CollectionModel.of(operationModels); + + entityModels.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withRel("class")); + + return ResponseEntity.ok(entityModels); } @GetMapping("/class/{className}/operation/{operationName}") - public ResponseEntity> getOperationByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String operationName) { - // Assuming ClassService has a method to get a single operation by name + public ResponseEntity> getOperationByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String operationName) throws UseApiException { OperationDTO operation = classService.getOperationByName(modelName, className, operationName); - EntityModel entityModel = EntityModel.of(operation); - entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, operationName)).withSelfRel()); - return ResponseEntity.ok(entityModel); + + EntityModel entityModels = EntityModel.of(operation); + + entityModels.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, operationName)).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getOperations(modelName, className)).withRel("operations")); + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withRel("class")); + + + return ResponseEntity.ok(entityModels); } @@ -90,16 +116,24 @@ public ResponseEntity> getOperationByName(@PathVariabl @PostMapping("/class/{className}/attribute") public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) throws UseApiException { AttributeDTO newAttribute = classService.createAttribute(modelName, className, attributeDTO); - EntityModel entityModel = EntityModel.of(newAttribute); - entityModel.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, newAttribute.getName())).withSelfRel()); - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + EntityModel entityModels = EntityModel.of(newAttribute); + + entityModels.add(linkTo(methodOn(ClassController.class).getAttributeByName(modelName, className, newAttribute.getName())).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withRel("class")); + + + return new ResponseEntity<>(entityModels, HttpStatus.CREATED); } @PostMapping("/class/{className}/operation") public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) throws UseApiException { OperationDTO newOperation = classService.createOperation(modelName, className, operationDTO); - EntityModel entityModel = EntityModel.of(newOperation); - entityModel.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, newOperation.getOperationName())).withSelfRel()); - return new ResponseEntity<>(entityModel, HttpStatus.CREATED); + + EntityModel entityModels = EntityModel.of(newOperation); + + entityModels.add(linkTo(methodOn(ClassController.class).getOperationByName(modelName, className, newOperation.getOperationName())).withSelfRel()); + entityModels.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, className)).withRel("class")); + + return new ResponseEntity<>(entityModels, HttpStatus.CREATED); } } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 0bad5846e..1e36a1c70 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -78,7 +78,7 @@ public ResponseEntity> getModelInvariantByName(@PathVa } @GetMapping("/models") - public ResponseEntity>> getAllModels() throws UseApiException { + public ResponseEntity>> getModels() throws UseApiException { List models = modelService.getAllModels(); List> modelEntities = new ArrayList<>(); @@ -88,12 +88,13 @@ public ResponseEntity>> getAllModels() thr entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelDTO.getName())).withRel("classes")); entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelDTO.getName())).withRel("associations")); entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelDTO.getName())).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelDTO.getName())).withRel("prePostConditions")); modelEntities.add(entityModel); } CollectionModel> collectionModel = CollectionModel.of(modelEntities); - collectionModel.add(linkTo(methodOn(ModelController.class).getAllModels()).withSelfRel()); + collectionModel.add(linkTo(methodOn(ModelController.class).getModels()).withSelfRel()); collectionModel.add(linkTo(methodOn(ModelController.class).createModel(null)).withRel("create model")); @@ -109,8 +110,9 @@ public ResponseEntity getClasses(@PathVariable String modelName) throws UseAp for (ClassDTO classOfModelName : modelClasses) { EntityModel entityModel = EntityModel.of(classOfModelName); - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); entityModel.add(linkTo(methodOn(ClassController.class).getClassByName(modelName, null)).withRel("class by name")); + entityModel.add(linkTo(methodOn(ClassController.class).addAttribute(modelName,null,null)).withRel("add attribute")); + entityModel.add(linkTo(methodOn(ClassController.class).addOperation(modelName,null,null)).withRel("add operation")); classEntities.add(entityModel); } @@ -192,7 +194,7 @@ public ResponseEntity>> getPreP collectionModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withSelfRel()); collectionModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - collectionModel.add(linkTo(methodOn(ModelController.class).createprepostcondition(modelName,null,null)).withRel("create prepostcondition")); + collectionModel.add(linkTo(methodOn(ModelController.class).createPrePostCondition(modelName,null,null)).withRel("create prepostcondition")); return new ResponseEntity<>(collectionModel, HttpStatus.OK); } @@ -224,21 +226,14 @@ public ResponseEntity> getModelPrePostCondByNam public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) throws UseApiException { ModelDTO createdModel = modelService.createModel(modelDTO); - // Create an EntityModel (HATEOAS) with the response EntityModel entityModel = EntityModel.of(createdModel); - // Add HATEOAS links - // Link to self - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(createdModel.getName())).withSelfRel()); - - // Link to get all classes in this model - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(createdModel.getName())).withRel("classes")); - - // Link to get all associations in this model - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(createdModel.getName())).withRel("associations")); - - // Link to get all invariants in this model - entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(createdModel.getName())).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).createModel(createdModel)).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).getModels()).withRel("models")); + entityModel.add(linkTo(methodOn(ModelController.class).createClass(modelDTO.getName(),null)).withRel("create class")); + entityModel.add(linkTo(methodOn(ModelController.class).createAssociation(modelDTO.getName(), null)).withRel("create association")); + entityModel.add(linkTo(methodOn(ModelController.class).createInvariant(modelDTO.getName(),null,null)).withRel("create invariant")); + entityModel.add(linkTo(methodOn(ModelController.class).createPrePostCondition(modelDTO.getName(), null,null)).withRel("create prepostcondition")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @@ -247,23 +242,14 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m public ResponseEntity> createClass(@PathVariable String modelName, @RequestBody ClassDTO classDTO) throws UseApiException { ClassDTO createdClass = modelService.createClass(modelName, classDTO); - // Wrap the created class in an EntityModel for HATEOAS EntityModel entityModel = EntityModel.of(createdClass); - // Link to the parent model + entityModel.add(linkTo(methodOn(ModelController.class).createClass(modelName,classDTO)).withSelfRel()); entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ClassController.class).addAttribute(modelName,classDTO.getName(),null)).withRel("add attribute")); + entityModel.add(linkTo(methodOn(ClassController.class).addOperation(modelName,classDTO.getName(),null)).withRel("add operation")); + entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); - // Link to the classes listing for this model (also used as self since there's no single-class GET) - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); - - // Link to create another class in this model - entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("class").withRel("create-class")); - - // Link to associations for this model - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); - - // Link to invariants for this model - entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @@ -274,8 +260,10 @@ public ResponseEntity> createAssociation(@PathVariab EntityModel entityModel = EntityModel.of(createdAssociation); - entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName, createdAssociation.getAssociationName())).withSelfRel()); + entityModel.add(linkTo(methodOn(ModelController.class).createAssociation(modelName, createdAssociation)).withSelfRel()); entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelAssociationByName(modelName,association.getAssociationName())).withRel("association by name")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @@ -284,48 +272,26 @@ public ResponseEntity> createAssociation(@PathVariab public ResponseEntity> createInvariant(@PathVariable String modelName, @PathVariable String className, @RequestBody InvariantDTO invariantDTO) throws UseApiException { InvariantDTO createdInvariant = modelService.createInvariant(modelName, invariantDTO, className); - // Wrap the created invariant in an EntityModel for HATEOAS EntityModel entityModel = EntityModel.of(createdInvariant); - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - - // Link to the invariants listing for this model (also used as self since there's no single-invariant GET) entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withSelfRel()); - - // Link to create another invariant in this model - entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("invariant").withRel("create-invariant")); - - // Link to classes for this model - entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withRel("classes")); - - // Link to associations for this model - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelInvariantByName(modelName, invariantDTO.getInvName())).withRel("invariant by name")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } @PostMapping("/model/{modelName}/{className}/prepostcondition") - public ResponseEntity> createprepostcondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) throws UseApiException { + public ResponseEntity> createPrePostCondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) throws UseApiException { PrePostConditionDTO createdPrePostCondition = modelService.createPrePostCondition(modelName, prePostConditionDTO, className); - // Wrap the created pre/post condition in an EntityModel for HATEOAS EntityModel entityModel = EntityModel.of(createdPrePostCondition); - // Link to the parent model - entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); - - // Link to the classes listing for this model (also used as self since there's no single-prepostcondition GET) entityModel.add(linkTo(methodOn(ModelController.class).getClasses(modelName)).withSelfRel()); - - // Link to create another pre/post condition in this model - entityModel.add(linkTo(ModelController.class).slash("model").slash(modelName).slash("prepostcondition").withRel("create-prepostcondition")); - - // Link to invariants for this model - entityModel.add(linkTo(methodOn(ModelController.class).getInvariants(modelName)).withRel("invariants")); - - // Link to associations for this model - entityModel.add(linkTo(methodOn(ModelController.class).getAssociations(modelName)).withRel("associations")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelByName(modelName)).withRel("model")); + entityModel.add(linkTo(methodOn(ModelController.class).getPrePostConditions(modelName)).withRel("prePostConditions")); + entityModel.add(linkTo(methodOn(ModelController.class).getModelPrePostCondByName(modelName, prePostConditionDTO.getName())).withRel("prepostcondition by name")); return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } From cc846aeda8036bbf0a196a013678d4c54f8d97c8 Mon Sep 17 00:00:00 2001 From: husakki Date: Mon, 8 Dec 2025 20:16:08 +0100 Subject: [PATCH 117/148] removed comments --- .../main/java/org/tzi/use/entities/ModelNTT.java | 1 - .../tzi/use/rest/controller/ClassController.java | 1 - .../tzi/use/rest/controller/ModelController.java | 16 +--------------- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java index a59bc39b9..7c7646bbe 100644 --- a/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java +++ b/use-api/src/main/java/org/tzi/use/entities/ModelNTT.java @@ -16,7 +16,6 @@ @Data @AllArgsConstructor @NoArgsConstructor -//@RequiredArgsConstructor public class ModelNTT { @Id private String name; diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 2a49a2669..4c94dfe5d 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 1e36a1c70..85a4ff97a 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -30,12 +30,6 @@ public class ModelController { // GET Mappings // ======================================== - /** - * Retrieve a model by its ID - * - * @param modelName The ID of the model to retrieve - * @return The model with HATEOAS links - */ @GetMapping("/model/{modelName}") public ResponseEntity> getModelByName(@PathVariable String modelName) throws UseApiException { ModelDTO modelDTO = modelService.getModelByName(modelName); @@ -126,9 +120,6 @@ public ResponseEntity getClasses(@PathVariable String modelName) throws UseAp } - /** - * Placeholder method to retrieve all associations in a model - */ @GetMapping("/model/{modelName}/associations") public ResponseEntity>> getAssociations(@PathVariable String modelName) throws UseApiException { List associations = modelService.getModelAssociations(modelName); @@ -216,12 +207,7 @@ public ResponseEntity> getModelPrePostCondByNam // POST Mappings // ======================================== - /** - * Create a new model - * - * @param modelDTO The model data to create - * @return The created model with HATEOAS links - */ + @PostMapping("/model") public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) throws UseApiException { ModelDTO createdModel = modelService.createModel(modelDTO); From e878701760f7e333f422f3a9088c8c791ab01c6a Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 02:18:20 +0100 Subject: [PATCH 118/148] Enhance class creation to include attributes and operations Updated UseModelFacade#createClass to accept a ClassNTT object and create its attributes and operations in addition to the class itself. Adjusted ModelService to use the new method signature. This was a mistake and the classes that were cached were wrongfully done so. --- .../src/main/java/org/tzi/use/UseModelFacade.java | 12 ++++++++++-- .../java/org/tzi/use/rest/services/ModelService.java | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 627753c2f..f26d552e9 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -17,9 +17,17 @@ public void createModel(String modelName) { new UseModelApi().createModel(modelName); } - public void createClass(ModelNTT modelNTT, String className) throws UseApiException { + public void createClass(ModelNTT modelNTT, ClassNTT classNTT) throws UseApiException { UseModelApi uma = getUMAfromModelNTT(modelNTT); - uma.createClass(className, false); + uma.createClass(classNTT.getName(), false); + + for (AttributeNTT attribute : classNTT.getAttributes()) { + uma.createAttribute(classNTT.getName(), attribute.getName(), attribute.getType()); + } + for (OperationNTT operation : classNTT.getOperations()) { + uma.createOperation(classNTT.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); + } +// umaCache.put(modelNTT.getName(), uma); } public void createInvariant(ModelNTT modelNTT, InvariantNTT invariant, String className) throws UseApiException { diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index dc41215e7..93a146474 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -53,7 +53,7 @@ public ClassDTO createClass(String modelName, ClassDTO classDTO) throws UseApiEx throw new DuplicateKeyException("Class name already exists in model: " + modelName); } - useModelFacade.createClass(modelNTT, classNTT.getName()); + useModelFacade.createClass(modelNTT, classNTT); modelNTT.getClasses().add(classNTT); modelRepo.save(modelNTT); From fc49d737e52589e78f2b4f671ad1578048075c54 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 02:26:38 +0100 Subject: [PATCH 119/148] manually added the tests and removed the old one since it deprecated --- ...se-webapi-extended.postman_collection.json | 1200 ------------- .../use-webapi.postman_collection.json | 1516 +++++++++++------ 2 files changed, 1034 insertions(+), 1682 deletions(-) delete mode 100644 use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json diff --git a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json deleted file mode 100644 index 943e28c60..000000000 --- a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi-extended.postman_collection.json +++ /dev/null @@ -1,1200 +0,0 @@ -{ - "info": { - "_postman_id": "e8a9f2d1-4f5c-4b2e-9a1c-3d5e6f7a8b9c", - "name": "use-webapi-extended", - "description": "Extended test collection for USE Web API with comprehensive test cases for models, classes, invariants, and associations", - "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", - "_exporter_id": "38619616" - }, - "item": [ - { - "name": "Model Tests", - "item": [ - { - "name": "Create Model - Success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response contains model data\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('name');", - " pm.expect(responseJson.name).to.equal('TestModel');", - "});", - "", - "pm.test(\"Response contains HATEOAS links\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name\": \"TestModel\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model" - }, - "response": [] - }, - { - "name": "Create Model - Empty Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400 or 500\", function () {", - " pm.expect([400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name\": \"\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model" - }, - "response": [] - }, - { - "name": "Get Model by Name - Success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response contains model data\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('name');", - "});", - "", - "pm.test(\"Response contains HATEOAS links\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - " pm.expect(responseJson._links).to.have.property('self');", - " pm.expect(responseJson._links).to.have.property('classes');", - " pm.expect(responseJson._links).to.have.property('invariants');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/TestModel" - }, - "response": [] - }, - { - "name": "Get Model by Name - Not Found", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 404 or 500\", function () {", - " pm.expect([404, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/NonExistentModel" - }, - "response": [] - }, - { - "name": "Get All Models", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response contains models collection\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('_embedded');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/models" - }, - "response": [] - } - ] - }, - { - "name": "Class Tests", - "item": [ - { - "name": "Create Class in Model - Success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response contains class data\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('name_mclass');", - " pm.expect(responseJson.name_mclass).to.equal('Person');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"Person\",\n \"attributes\": [\n {\n \"name_attr\": \"name\",\n \"type\": \"String\"\n },\n {\n \"name_attr\": \"age\",\n \"type\": \"Integer\"\n }\n ],\n \"operations\": [\n {\n \"head\": \"getFullInfo()\",\n \"body\": null\n }\n ]\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Class - Multiple Attributes Different Types", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response contains all attributes\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson.attributes).to.be.an('array');", - " pm.expect(responseJson.attributes).to.have.lengthOf(5);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"Employee\",\n \"attributes\": [\n {\n \"name_attr\": \"id\",\n \"type\": \"Integer\"\n },\n {\n \"name_attr\": \"firstName\",\n \"type\": \"String\"\n },\n {\n \"name_attr\": \"lastName\",\n \"type\": \"String\"\n },\n {\n \"name_attr\": \"salary\",\n \"type\": \"Real\"\n },\n {\n \"name_attr\": \"isActive\",\n \"type\": \"Boolean\"\n }\n ],\n \"operations\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Class - Multiple Operations", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response contains all operations\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson.operations).to.be.an('array');", - " pm.expect(responseJson.operations).to.have.lengthOf(3);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"Calculator\",\n \"attributes\": [],\n \"operations\": [\n {\n \"head\": \"add(a:Integer, b:Integer):Integer\",\n \"body\": null\n },\n {\n \"head\": \"subtract(a:Integer, b:Integer):Integer\",\n \"body\": null\n },\n {\n \"head\": \"multiply(a:Integer, b:Integer):Integer\",\n \"body\": null\n }\n ]\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Get Model Classes - Success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response contains classes collection\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('_embedded');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/TestModel/classes" - }, - "response": [] - }, - { - "name": "Create Class - Invalid Attribute Type", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400 or 500\", function () {", - " pm.expect([400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"InvalidClass\",\n \"attributes\": [\n {\n \"name_attr\": \"field\",\n \"type\": \"InvalidType\"\n }\n ],\n \"operations\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Class - Null Attributes", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201 or handles null gracefully\", function () {", - " pm.expect([201, 400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"NullAttributesClass\",\n \"attributes\": null,\n \"operations\": null\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - } - ] - }, - { - "name": "Invariant Tests", - "item": [ - { - "name": "Create Invariant - Success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response contains invariant data\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('invName');", - " pm.expect(responseJson).to.have.property('invBody');", - "});", - "", - "pm.test(\"Response contains HATEOAS links\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"PositiveAge\",\n \"invBody\": \"self.age > 0\",\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Person/invariant" - }, - "response": [] - }, - { - "name": "Create Invariant - Existential", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Invariant is existential\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson.isExistential).to.be.true;", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"HasEmployees\",\n \"invBody\": \"Employee.allInstances()->notEmpty()\",\n \"isExistential\": true\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Employee/invariant" - }, - "response": [] - }, - { - "name": "Create Invariant - Empty Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400 or 500\", function () {", - " pm.expect([400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"\",\n \"invBody\": \"self.age > 0\",\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Person/invariant" - }, - "response": [] - }, - { - "name": "Create Invariant - Empty Body", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400 or 500\", function () {", - " pm.expect([400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"EmptyBodyInv\",\n \"invBody\": \"\",\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Person/invariant" - }, - "response": [] - }, - { - "name": "Get Model Invariants - Success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response contains invariants collection\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.be.an('object');", - " pm.expect(responseJson).to.have.property('_embedded');", - "});", - "", - "pm.test(\"Response contains HATEOAS links\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - " pm.expect(responseJson._links).to.have.property('self');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/TestModel/invariants" - }, - "response": [] - }, - { - "name": "Create Invariant - Complex Expression", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response contains complex invariant\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson.invName).to.equal('ValidSalary');", - " pm.expect(responseJson.invBody).to.include('salary');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"ValidSalary\",\n \"invBody\": \"self.salary >= 0 and self.salary <= 1000000\",\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Employee/invariant" - }, - "response": [] - } - ] - }, - { - "name": "Edge Cases and Error Handling", - "item": [ - { - "name": "Create Model - Duplicate Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400, 409, or 500\", function () {", - " pm.expect([400, 409, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name\": \"TestModel\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model" - }, - "response": [] - }, - { - "name": "Create Class - Duplicate Class Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400, 409, or 500\", function () {", - " pm.expect([400, 409, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"Person\",\n \"attributes\": [],\n \"operations\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Class - Special Characters in Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Response code indicates success or validation error\", function () {", - " pm.expect([201, 400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"Class@#$%\",\n \"attributes\": [],\n \"operations\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Class - Very Long Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Response code indicates success or validation error\", function () {", - " pm.expect([201, 400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"ThisIsAVeryLongClassNameThatExceedsNormalExpectationsAndMightCauseIssuesWithTheSystem\",\n \"attributes\": [],\n \"operations\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Invariant - Non-existent Class", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 404 or 500\", function () {", - " pm.expect([404, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"SomeInvariant\",\n \"invBody\": \"self.field > 0\",\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/NonExistentClass/invariant" - }, - "response": [] - }, - { - "name": "Get Classes - Non-existent Model", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 404 or 500\", function () {", - " pm.expect([404, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/NonExistentModel/classes" - }, - "response": [] - } - ] - }, - { - "name": "Performance Tests", - "item": [ - { - "name": "GET Models - Response Time", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response time is below 500ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(500);", - "});", - "", - "pm.test(\"Response time is below 1000ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(1000);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/models" - }, - "response": [] - }, - { - "name": "POST Model - Response Time", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "let iter = pm.info.iteration || 0;", - "let uniqueName = `PerfModel-${iter}-${Date.now()}`;", - "pm.environment.set(\"uniqueModelName\", uniqueName);" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response time is below 500ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(500);", - "});", - "", - "pm.test(\"Response time is below 1000ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(1000);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name\": \"{{uniqueModelName}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model" - }, - "response": [] - }, - { - "name": "POST Class with Large Payload - Response Time", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "let iter = pm.info.iteration || 0;", - "let uniqueName = `LargeClass-${iter}-${Date.now()}`;", - "pm.environment.set(\"uniqueClassName\", uniqueName);" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response time is below 1000ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(1000);", - "});", - "", - "pm.test(\"Response time is below 2000ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(2000);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"{{uniqueClassName}}\",\n \"attributes\": [\n {\"name_attr\": \"attr1\", \"type\": \"String\"},\n {\"name_attr\": \"attr2\", \"type\": \"String\"},\n {\"name_attr\": \"attr3\", \"type\": \"Integer\"},\n {\"name_attr\": \"attr4\", \"type\": \"Real\"},\n {\"name_attr\": \"attr5\", \"type\": \"Boolean\"},\n {\"name_attr\": \"attr6\", \"type\": \"String\"},\n {\"name_attr\": \"attr7\", \"type\": \"String\"},\n {\"name_attr\": \"attr8\", \"type\": \"Integer\"},\n {\"name_attr\": \"attr9\", \"type\": \"Real\"},\n {\"name_attr\": \"attr10\", \"type\": \"Boolean\"}\n ],\n \"operations\": [\n {\"head\": \"operation1()\", \"body\": null},\n {\"head\": \"operation2()\", \"body\": null},\n {\"head\": \"operation3()\", \"body\": null},\n {\"head\": \"operation4()\", \"body\": null},\n {\"head\": \"operation5()\", \"body\": null}\n ]\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "GET Model by Name - Response Time", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response time is below 300ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(300);", - "});", - "", - "pm.test(\"Response time is below 500ms\", function () {", - " pm.expect(pm.response.responseTime).to.be.below(500);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/TestModel" - }, - "response": [] - } - ] - }, - { - "name": "HATEOAS and Link Validation", - "item": [ - { - "name": "Verify Model Links Structure", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response has HATEOAS _links object\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - " pm.expect(responseJson._links).to.be.an('object');", - "});", - "", - "pm.test(\"Self link is present and valid\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson._links).to.have.property('self');", - " pm.expect(responseJson._links.self).to.have.property('href');", - "});", - "", - "pm.test(\"Related resource links are present\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson._links).to.have.property('classes');", - " pm.expect(responseJson._links).to.have.property('invariants');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/TestModel" - }, - "response": [] - }, - { - "name": "Verify Classes Collection Links", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "pm.test(\"Response has HATEOAS structure\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - " pm.expect(responseJson).to.have.property('_embedded');", - "});", - "", - "pm.test(\"Self link is present\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson._links).to.have.property('self');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/api/model/TestModel/classes" - }, - "response": [] - }, - { - "name": "Verify Invariant Creation Links", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {", - " pm.response.to.have.status(201);", - "});", - "", - "pm.test(\"Response has HATEOAS links\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson).to.have.property('_links');", - "});", - "", - "pm.test(\"Model link is present\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson._links).to.have.property('model');", - "});", - "", - "pm.test(\"Self link is present\", function () {", - " const responseJson = pm.response.json();", - " pm.expect(responseJson._links).to.have.property('self');", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"invName\": \"LinkTestInvariant\",\n \"invBody\": \"true\",\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Person/invariant" - }, - "response": [] - } - ] - }, - { - "name": "Data Validation Tests", - "item": [ - { - "name": "Create Class - Missing Request Body", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Model - Malformed JSON", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"name\": \"TestModel\",", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model" - }, - "response": [] - }, - { - "name": "Create Class - Wrong Data Type for Attributes", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400 or 500\", function () {", - " pm.expect([400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"name_mclass\": \"WrongTypeClass\",\n \"attributes\": \"not-an-array\",\n \"operations\": []\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/class" - }, - "response": [] - }, - { - "name": "Create Invariant - Missing Required Fields", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400 or 500\", function () {", - " pm.expect([400, 500]).to.include(pm.response.code);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"isExistential\": false\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/api/model/TestModel/Person/invariant" - }, - "response": [] - } - ] - } - ] -} diff --git a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json index 3555d7aa3..84ea4e06e 100644 --- a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json +++ b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json @@ -1,484 +1,1036 @@ { - "info": { - "_postman_id": "10464710-2286-4379-89c4-f0c29739d9fb", - "name": "use-webapi", - "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", - "_exporter_id": "38619616" - }, - "item": [ - { - "name": "empty class", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {\r", - " pm.response.to.have.status(201);\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"name_mclass\": \"MyClass\"\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "normal class", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {\r", - " pm.response.to.have.status(201);\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"name_mclass\": \"MyClass3443\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"MyAttr232\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"MyAttr44242\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"operation()1223\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "no class name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"A class must be named\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"name_mclass\": \"\"\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "basic GET", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"Response is an array\", function () {\r", - " pm.expect(pm.response.json()).to.be.an('array');\r", - "});\r", - "\r", - "pm.test(\"Response contains valid UseClass objects\", function () {\r", - " const responseJson = pm.response.json();\r", - " pm.expect(responseJson).to.be.an('array');\r", - " \r", - " if (responseJson.length > 0) {\r", - " responseJson.forEach((useClass) => {\r", - " pm.expect(useClass).to.have.property('name_mclass');\r", - " pm.expect(useClass.attributes).to.be.an('array');\r", - " pm.expect(useClass.operations).to.be.an('array');\r", - " });\r", - " }\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": "localhost:8080/classes" - }, - "response": [] - }, - { - "name": "basic POST success", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 201\", function () {\r", - " pm.response.to.have.status(201);\r", - "});\r", - "\r", - "pm.test(\"Response contains the created UseClass object\", function () {\r", - " const responseJson = pm.response.json();\r", - " pm.expect(responseJson).to.be.an('object');\r", - " pm.expect(responseJson).to.have.property('name_mclass');\r", - " pm.expect(responseJson).to.have.property('attributes').that.is.an('array');\r", - " pm.expect(responseJson).to.have.property('operations').that.is.an('array');\r", - "});\r", - "\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"name_mclass\": \"ExampleClass\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "basic POST fail", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Error message is returned for invalid model\", function () {\r", - " const responseText = pm.response.text(); // Fixed variable name\r", - " pm.expect(responseText).to.be.a('string');\r", - " pm.expect(responseText).to.include(\"A class must be named\"); // Updated error message\r", - "});\r", - "// Add a test to check the length of the response data\r", - "pm.test(\"Response data length is greater than 0\", function () {\r", - " const responseData = pm.response.text(); \r", - " pm.expect(responseData.length).to.be.greaterThan(0, \"Response data should not be empty\");\r", - "});\r", - "\r", - "pm.test(\"Response time is within an acceptable range\", function () {\r", - " pm.expect(pm.response.responseTime).to.be.below(1000);\r", - "});\r", - "\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"Attribute1\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"Operation1\",\r\n \"body\": null\r\n }\r\n ]\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "duplicate class", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Class name already exists\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "duplicate attribute", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Attribute creation failed!\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDoubleAttr\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "duplicate operation", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Operation creation failed!\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassDupOperation\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n },\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "no attribute name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Modelelement without name\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoAttrName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "no operation name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 400\", function () {\r", - " pm.response.to.have.status(400);\r", - "});\r", - "\r", - "pm.test(\"Body is correct\", function () {\r", - " pm.response.to.have.body(\"Operation name is required!\");\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"TestClassNoOperationName\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - }, - { - "name": "POST performance", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "// Generate a unique name using an iteration counter and timestamp\r", - "let iter = pm.info.iteration || 0;\r", - "let uniqueName = `Class-${iter}-${Date.now()}`;\r", - "\r", - "pm.environment.set(\"uniqueName\", uniqueName);\r", - "\r", - "console.log(\"Generated unique name: \" + uniqueName);" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Response time is below 20ms\", function () {\r", - " pm.expect(pm.response.responseTime).to.be.below(20);\r", - "});\r", - "\r", - "pm.test(\"Response time is below 100ms\", function () {\r", - " pm.expect(pm.response.responseTime).to.be.below(100);\r", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "\r\n {\r\n \"name_mclass\": \"{{uniqueName}}\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }\r\n {\r\n \"name_mclass\": \"TestClass2\",\r\n \"attributes\": [\r\n {\r\n \"name_attr\": \"name224\",\r\n \"type\": \"String\"\r\n },\r\n {\r\n \"name_attr\": \"name23\",\r\n \"type\": \"String\"\r\n }\r\n ],\r\n \"operations\": [\r\n {\r\n \"head\": \"123\",\r\n \"body\": null\r\n }\r\n ]\r\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "localhost:8080/class" - }, - "response": [] - } - ] + "info": { + "_postman_id": "c1a2b3c4-d5e6-f7g8-h9i0-j1k2l3m4n5o6", + "name": "use-webapi-system-tests", + "description": "Comprehensive test collection for USE Web API with thorough test cases.", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "Model Operations", + "item": [ + { + "name": "Create Model - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test('Response contains model name', function () {", + " const json = pm.response.json();", + " pm.expect(json.name).to.equal('ComprehensiveTestModel');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"ComprehensiveTestModel\"}" + }, + "url": "localhost:8080/api/model" + } + }, + { + "name": "Create Model - Duplicate Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 409 Conflict for duplicate', function () {", + " pm.response.to.have.status(409);", + "});", + "pm.test('Error message indicates duplicate', function () {", + " const json = pm.response.json();", + " pm.expect(json.message).to.include('already exists');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"ComprehensiveTestModel\"}" + }, + "url": "localhost:8080/api/model" + } + }, + { + "name": "Create Model - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"\"}" + }, + "url": "localhost:8080/api/model" + } + }, + { + "name": "Create Model - Null Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 or 500', function () {", + " pm.expect([400, 500]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": null}" + }, + "url": "localhost:8080/api/model" + } + }, + { + "name": "Get Model by Name - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test('Response contains model data', function () {", + " const json = pm.response.json();", + " pm.expect(json.name).to.equal('ComprehensiveTestModel');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel" + } + }, + { + "name": "Get Model by Name - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request for not found', function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test('Error message indicates not found', function () {", + " const json = pm.response.json();", + " pm.expect(json.message).to.include('not found');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/NonExistentModel123" + } + }, + { + "name": "Get All Models", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test('Response time is acceptable', function () {", + " pm.expect(pm.response.responseTime).to.be.below(1000);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models" + } + } + ] + }, + { + "name": "Class Operations", + "item": [ + { + "name": "Create Class - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test('Response contains class name', function () {", + " const json = pm.response.json();", + " pm.expect(json.name).to.equal('Person');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"Person\", \"attributes\": [{\"name\": \"firstName\", \"type\": \"String\"}, {\"name\": \"age\", \"type\": \"Integer\"}], \"operations\": []}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/class" + } + }, + { + "name": "Create Class - Duplicate Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 409 Conflict', function () {", + " pm.response.to.have.status(409);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"Person\", \"attributes\": [], \"operations\": []}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/class" + } + }, + { + "name": "Create Class - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"\", \"attributes\": [], \"operations\": []}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/class" + } + }, + { + "name": "Create Class - Non-existent Model", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test('Error indicates model not found', function () {", + " const json = pm.response.json();", + " pm.expect(json.message).to.include('not found');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"TestClass\", \"attributes\": [], \"operations\": []}" + }, + "url": "localhost:8080/api/model/FakeModel999/class" + } + }, + { + "name": "Get Classes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel/classes" + } + }, + { + "name": "Get Class by Name - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test('Response contains class data', function () {", + " const json = pm.response.json();", + " pm.expect(json.name).to.equal('Person');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person" + } + }, + { + "name": "Get Class by Name - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/NonExistentClass" + } + } + ] + }, + { + "name": "Attribute Operations", + "item": [ + { + "name": "Add Attribute - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test('Response contains attribute', function () {", + " const json = pm.response.json();", + " pm.expect(json.name).to.equal('email');", + " pm.expect(json.type).to.equal('String');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"email\", \"type\": \"String\"}" + }, + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute" + } + }, + { + "name": "Add Attribute - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"\", \"type\": \"String\"}" + }, + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute" + } + }, + { + "name": "Add Attribute - Invalid Type", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"badAttr\", \"type\": \"InvalidType\"}" + }, + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute" + } + }, + { + "name": "Get Attributes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attributes" + } + }, + { + "name": "Get Attribute by Name - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test('Response contains attribute name', function () {", + " const json = pm.response.json();", + " pm.expect(json.name).to.equal('firstName');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute/firstName" + } + }, + { + "name": "Get Attribute by Name - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute/nonExistentAttr" + } + } + ] + }, + { + "name": "Operation (Method) Tests", + "item": [ + { + "name": "Add Operation - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test('Response contains operation', function () {", + " const json = pm.response.json();", + " pm.expect(json.operationName).to.equal('getInfo');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"operationName\": \"getInfo\", \"parameter\": [], \"returnType\": \"String\"}" + }, + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/operation" + } + }, + { + "name": "Add Operation - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"operationName\": \"\", \"parameter\": [], \"returnType\": \"String\"}" + }, + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/operation" + } + }, + { + "name": "Get Operations", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/operations" + } + }, + { + "name": "Get Operation by Name - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/operation/nonExistentOp" + } + } + ] + }, + { + "name": "Association Operations", + "item": [ + { + "name": "Create Second Class for Association", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"name\": \"Company\", \"attributes\": [{\"name\": \"companyName\", \"type\": \"String\"}], \"operations\": []}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/class" + } + }, + { + "name": "Create Association - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test('Response contains association name', function () {", + " const json = pm.response.json();", + " pm.expect(json.associationName).to.equal('WorksFor');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"associationName\": \"WorksFor\", \"end1ClassName\": \"Person\", \"end1RoleName\": \"employee\", \"end1Multiplicity\": \"*\", \"end1Aggregation\": \"NONE\", \"end2ClassName\": \"Company\", \"end2RoleName\": \"employer\", \"end2Multiplicity\": \"0..1\", \"end2Aggregation\": \"NONE\"}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/association" + } + }, + { + "name": "Create Association - Non-existent Class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"associationName\": \"BadAssoc\", \"end1ClassName\": \"NonExistent\", \"end1RoleName\": \"role1\", \"end1Multiplicity\": \"*\", \"end1Aggregation\": \"NONE\", \"end2ClassName\": \"Person\", \"end2RoleName\": \"role2\", \"end2Multiplicity\": \"1\", \"end2Aggregation\": \"NONE\"}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/association" + } + }, + { + "name": "Get Associations", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel/associations" + } + } + ] + }, + { + "name": "Invariant Operations", + "item": [ + { + "name": "Create Invariant - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test('Response contains invariant data', function () {", + " const json = pm.response.json();", + " pm.expect(json.invName).to.equal('PositiveAge');", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"invName\": \"PositiveAge\", \"invBody\": \"self.age > 0\", \"isExistential\": false}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/Person/invariant" + } + }, + { + "name": "Create Invariant - Empty Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"invName\": \"\", \"invBody\": \"self.age > 0\", \"isExistential\": false}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/Person/invariant" + } + }, + { + "name": "Create Invariant - Empty Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"invName\": \"EmptyBodyInv\", \"invBody\": \"\", \"isExistential\": false}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/Person/invariant" + } + }, + { + "name": "Create Invariant - Non-existent Class", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"invName\": \"SomeInv\", \"invBody\": \"true\", \"isExistential\": false}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/FakeClass999/invariant" + } + }, + { + "name": "Get Invariants", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel/invariants" + } + } + ] + }, + { + "name": "PrePostCondition Operations", + "item": [ + { + "name": "Create PreCondition - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 201 Created', function () {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"operationName\": \"getInfo\", \"name\": \"validPerson\", \"condition\": \"self.age > 0\", \"isPre\": true}" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/Person/prepostcondition" + } + }, + { + "name": "Get PrePostConditions", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200 OK', function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel/prepostconditions" + } + } + ] + }, + { + "name": "Error Handling", + "item": [ + { + "name": "Invalid JSON Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{invalid json}" + }, + "url": "localhost:8080/api/model" + } + }, + { + "name": "Missing Content-Type Header", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 or 415', function () {", + " pm.expect([400, 415]).to.include(pm.response.code);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\"name\": \"TestModel\"}" + }, + "url": "localhost:8080/api/model" + } + }, + { + "name": "Empty Request Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "" + }, + "url": "localhost:8080/api/model/ComprehensiveTestModel/class" + } + } + ] + }, + { + "name": "Performance Tests", + "item": [ + { + "name": "GET Models Performance", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test('Response time below 500ms', function () {", + " pm.expect(pm.response.responseTime).to.be.below(500);", + "});", + "pm.test('Response time below 1000ms', function () {", + " pm.expect(pm.response.responseTime).to.be.below(1000);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/models" + } + }, + { + "name": "GET Model by Name Performance", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test('Response time below 300ms', function () {", + " pm.expect(pm.response.responseTime).to.be.below(300);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel" + } + } + ] + } + ] } \ No newline at end of file From 53c05886317c22b76646f1463376ef7ac51afbe4 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 02:58:49 +0100 Subject: [PATCH 120/148] Update base image in Dockerfile to eclipse-temurin --- use-api/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/Dockerfile b/use-api/Dockerfile index 7f81784de..31b134dd8 100644 --- a/use-api/Dockerfile +++ b/use-api/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:21-jdk-slim +FROM eclipse-temurin:21-jdk WORKDIR /app From 7f5156f0765cf02f8b7427395e720c1c10725276 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 02:58:59 +0100 Subject: [PATCH 121/148] removed the sleep and now is healthcheck --- .github/workflows/maven.yml | 5 +---- use-api/docker-compose.yml | 6 ++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 102bcaf2c..291737394 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -91,10 +91,7 @@ jobs: run: mkdir target && cp use-api-7.1.1.jar target - name: Run docker compose - run: docker compose up -d - - - name: Wait for docker to be ready - run: sleep 20 + run: docker compose up -d --wait - name: Run Postman tests run: | diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index 1c7a973ba..367623aff 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -22,6 +22,12 @@ services: - mongodb environment: - SPRING_DATA_MONGODB_HOST=mongodb_cicd + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:8080/" ] # Or /actuator/health if using Spring Actuator + interval: 5s + timeout: 5s + retries: 10 + start_period: 15s volumes: mongodb_data: \ No newline at end of file From 851bb65479094d1ddd1847bde85e506fd9a012eb Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 03:45:11 +0100 Subject: [PATCH 122/148] Refactor Maven CI workflow and improve Docker handling --- .github/workflows/maven.yml | 106 +++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 291737394..77d754764 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -43,61 +43,79 @@ jobs: with: name: constructed_use-api path: testphase + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'adopt' + cache: maven - - name: Upload postman tests - run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests - - uses: actions/upload-artifact@v4 - with: - name: postman_tests - path: postmantests + - name: Build with Maven + run: mvn --batch-mode --update-snapshots verify - - name: Upload docker image - run: mkdir docker && cp use-api/docker-compose.yml docker && cp use-api/Dockerfile docker - - uses: actions/upload-artifact@v4 - with: - name: docker_image - path: docker + - name: Upload build result use-assembly + run: mkdir staging && cp use-assembly/target/*.zip staging + - uses: actions/upload-artifact@v4 + with: + name: Package + path: staging + + - name: Upload build result use-api + run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase + - uses: actions/upload-artifact@v4 + with: + name: build_use-api + path: testphase + - name: Upload postman tests + run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests + - uses: actions/upload-artifact@v4 + with: + name: postman_tests + path: postmantests + - name: Build and Save Docker Image + run: docker build -t use-api:latest ./use-api && docker save -o use-api.tar use-api:latest + + - name: Upload Docker Image Tar + uses: actions/upload-artifact@v4 + with: + name: docker_image_tar + path: use-api.tar + + - name: Upload docker config + run: mkdir docker-config && cp use-api/docker-compose.yml docker-config && cp use-api/Dockerfile docker-config + - uses: actions/upload-artifact@v4 + with: + name: docker_config + path: docker-config test: needs: build runs-on: ubuntu-latest - steps: - - name: Set up Java - uses: actions/setup-java@v3 - with: - java-version: '21' - distribution: 'adopt' + - name: Download Artifacts + uses: actions/download-artifact@v4 + - name: Load Docker Image + run: docker load -i docker_image_tar/use-api.tar - - name: Download Artifact use-api jar - uses: actions/download-artifact@v4 - with: - name: constructed_use-api - - - name: Download Artifact postman tests - uses: actions/download-artifact@v4 - with: - name: postman_tests - - - name: Download Aritfact Dockerimage - uses: actions/download-artifact@v4 - with: - name: docker_image + - name: Prepare Test Files + run: | + mkdir -p target + cp build_use-api/use-api-7.1.1.jar target/ + cp docker_config/docker-compose.yml . + cp postman_tests/use-webapi.postman_collection.json . - - name: move the jar - run: mkdir target && cp use-api-7.1.1.jar target + - name: Run docker compose + run: docker compose up -d --wait - - name: Run docker compose - run: docker compose up -d --wait - - - name: Run Postman tests - run: | - npm install -g newman - newman run use-webapi.postman_collection.json + - name: Run Postman tests + run: | + npm install -g newman + newman run use-webapi.postman_collection.json - - name: Stop services - if: always() - run: docker-compose down + - name: Stop services + if: always() + run: docker compose down \ No newline at end of file From d863cb3881fdb7958517a10708fad438ac06f6e5 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Thu, 18 Dec 2025 02:35:19 +0100 Subject: [PATCH 123/148] Change base image to eclipse-temurin:21-jdk-slim openjdk deprecated --- use-api/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/Dockerfile b/use-api/Dockerfile index 31b134dd8..dc090e9b3 100644 --- a/use-api/Dockerfile +++ b/use-api/Dockerfile @@ -6,4 +6,4 @@ COPY target/use-api-*.jar app.jar EXPOSE 8080 -ENTRYPOINT ["java","-jar","app.jar"] \ No newline at end of file +ENTRYPOINT ["java","-jar","app.jar"] From 97654e10e542b6dce00d9f4365e02153551d0779 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Thu, 18 Dec 2025 02:43:57 +0100 Subject: [PATCH 124/148] Update docker-compose command to use new syntax --- .github/workflows/maven.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 77d754764..77eb15fb7 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -116,6 +116,14 @@ jobs: npm install -g newman newman run use-webapi.postman_collection.json - - name: Stop services - if: always() - run: docker compose down \ No newline at end of file + - name: Wait for docker to be ready + run: sleep 20 + + - name: Run Postman tests + run: | + npm install -g newman + newman run use-webapi.postman_collection.json + + - name: Stop services + if: always() + run: docker compose down From 7f27beb4b6691838259b244977e9b585905d8fa0 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 03:51:12 +0100 Subject: [PATCH 125/148] Revert "Refactor Maven CI workflow and improve Docker handling" This reverts commit 8e0720793f651e58f1d634bf71d7061ad062876c. --- .github/workflows/maven.yml | 101 ++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 56 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 77eb15fb7..d1f891499 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,9 +1,14 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + name: Java CI with Maven on: push jobs: build: + runs-on: ubuntu-latest + steps: - uses: actions/checkout@v4 - name: Set up JDK @@ -51,70 +56,54 @@ jobs: distribution: 'adopt' cache: maven - - name: Build with Maven - run: mvn --batch-mode --update-snapshots verify - - - name: Upload build result use-assembly - run: mkdir staging && cp use-assembly/target/*.zip staging - - uses: actions/upload-artifact@v4 - with: - name: Package - path: staging - - - name: Upload build result use-api - run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase - - uses: actions/upload-artifact@v4 - with: - name: build_use-api - path: testphase - - - name: Upload postman tests - run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests - - uses: actions/upload-artifact@v4 - with: - name: postman_tests - path: postmantests + - name: Upload postman tests + run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests + - uses: actions/upload-artifact@v4 + with: + name: postman_tests + path: postmantests - - name: Build and Save Docker Image - run: docker build -t use-api:latest ./use-api && docker save -o use-api.tar use-api:latest + - name: Upload docker image + run: mkdir docker && cp use-api/docker-compose.yml docker && cp use-api/Dockerfile docker + - uses: actions/upload-artifact@v4 + with: + name: docker_image + path: docker - - name: Upload Docker Image Tar - uses: actions/upload-artifact@v4 - with: - name: docker_image_tar - path: use-api.tar - - name: Upload docker config - run: mkdir docker-config && cp use-api/docker-compose.yml docker-config && cp use-api/Dockerfile docker-config - - uses: actions/upload-artifact@v4 - with: - name: docker_config - path: docker-config test: needs: build runs-on: ubuntu-latest + steps: - - name: Download Artifacts - uses: actions/download-artifact@v4 - - - name: Load Docker Image - run: docker load -i docker_image_tar/use-api.tar - - - name: Prepare Test Files - run: | - mkdir -p target - cp build_use-api/use-api-7.1.1.jar target/ - cp docker_config/docker-compose.yml . - cp postman_tests/use-webapi.postman_collection.json . - - - name: Run docker compose - run: docker compose up -d --wait - - - name: Run Postman tests - run: | - npm install -g newman - newman run use-webapi.postman_collection.json + - name: Set up Java + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'adopt' + + + - name: Download Artifact use-api jar + uses: actions/download-artifact@v4 + with: + name: constructed_use-api + + - name: Download Artifact postman tests + uses: actions/download-artifact@v4 + with: + name: postman_tests + + - name: Download Aritfact Dockerimage + uses: actions/download-artifact@v4 + with: + name: docker_image + + - name: move the jar + run: mkdir target && cp use-api-7.1.1.jar target + + - name: Run docker compose + run: docker compose up -d --wait - name: Wait for docker to be ready run: sleep 20 From 3ce265dd3915974de785b9bbdc1309706aa62d69 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 09:14:51 +0100 Subject: [PATCH 126/148] healtcheck actuator --- use-api/docker-compose.yml | 4 ++-- use-api/pom.xml | 4 ++++ use-api/src/main/resources/application.properties | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index 367623aff..ea759bdab 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -23,11 +23,11 @@ services: environment: - SPRING_DATA_MONGODB_HOST=mongodb_cicd healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8080/" ] # Or /actuator/health if using Spring Actuator + test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health"" ] # Or /actuator/health if using Spring Actuator interval: 5s timeout: 5s retries: 10 - start_period: 15s + start_period: 40s volumes: mongodb_data: \ No newline at end of file diff --git a/use-api/pom.xml b/use-api/pom.xml index 17b6807c4..55da9509e 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -91,6 +91,10 @@ spring-boot-starter-test test + + org.springframework.boot + spring-boot-starter-actuator + org.springframework spring-webflux diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index 6c231f1ef..f3dbe100d 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -18,3 +18,7 @@ spring.data.mongodb.password=rootpass spring.data.mongodb.database=use-database spring.data.mongodb.port=27017 spring.data.mongodb.host=localhost + +# Actuator configuration +management.endpoints.web.exposure.include=health +management.endpoint.health.show-details=when-authorized From 1a54385a1506b6f74db3137d69be3d1b39205429 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Thu, 18 Dec 2025 03:58:38 +0100 Subject: [PATCH 127/148] Increase start period for health check to 40 seconds --- use-api/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index ea759bdab..ff62a86e2 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -30,4 +30,4 @@ services: start_period: 40s volumes: - mongodb_data: \ No newline at end of file + mongodb_data: From e94efecaf3d302b59e3cfdac89651a4266b4282e Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Thu, 18 Dec 2025 04:03:17 +0100 Subject: [PATCH 128/148] removed --wait --- .github/workflows/maven.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d1f891499..da8160fc3 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -103,7 +103,8 @@ jobs: run: mkdir target && cp use-api-7.1.1.jar target - name: Run docker compose - run: docker compose up -d --wait + #run: docker compose up -d --wait + run: docker compose up -d - name: Wait for docker to be ready run: sleep 20 From 6e5a7b4bba250d6d3760fb5440a1eac9008961f6 Mon Sep 17 00:00:00 2001 From: husakki <81704101+husakki@users.noreply.github.com> Date: Thu, 18 Dec 2025 04:04:31 +0100 Subject: [PATCH 129/148] sleep Added a step to wait for Docker to be ready before running Postman tests. --- .github/workflows/maven.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index da8160fc3..04583269b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -105,6 +105,9 @@ jobs: - name: Run docker compose #run: docker compose up -d --wait run: docker compose up -d + + - name: Wait for docker to be ready + run: sleep 20 - name: Wait for docker to be ready run: sleep 20 From 55621b3c509190b506138d70402b2161130cb7f8 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 09:16:02 +0100 Subject: [PATCH 130/148] removed sleep again --- .github/workflows/maven.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 04583269b..9b688fabb 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -104,10 +104,8 @@ jobs: - name: Run docker compose #run: docker compose up -d --wait - run: docker compose up -d - - - name: Wait for docker to be ready - run: sleep 20 + run: docker compose up -d --wait + - name: Wait for docker to be ready run: sleep 20 From 82cb352c63245840509d910f36b86421dfa0fc9c Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 09:22:42 +0100 Subject: [PATCH 131/148] typo --- use-api/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index ff62a86e2..1f5f27363 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -23,7 +23,7 @@ services: environment: - SPRING_DATA_MONGODB_HOST=mongodb_cicd healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health"" ] # Or /actuator/health if using Spring Actuator + test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] # Or /actuator/health if using Spring Actuator interval: 5s timeout: 5s retries: 10 From 25b153b384a54eed64d87554f34a248da6ab67e2 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 09:37:42 +0100 Subject: [PATCH 132/148] better openapi comments --- .../use/rest/controller/ClassController.java | 8 ++++++++ .../use/rest/controller/ModelController.java | 18 +++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 4c94dfe5d..8d4af4ad3 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -1,5 +1,6 @@ package org.tzi.use.rest.controller; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -29,6 +30,7 @@ public class ClassController { private final ClassService classService; + @Operation(summary = "Get a class by name", description = "Returns one class of the model") @GetMapping("/class/{className}") public ResponseEntity> getClassByName(@PathVariable String modelName, @PathVariable String className) throws UseApiException { ClassDTO classDTO = classService.getClassByName(modelName, className); @@ -43,6 +45,7 @@ public ResponseEntity> getClassByName(@PathVariable String return ResponseEntity.ok(entityModels); } + @Operation(summary = "List attributes of a class", description = "Lists every attribute of the class") @GetMapping("/class/{className}/attributes") public ResponseEntity>> getAttributes(@PathVariable String modelName, @PathVariable String className) throws UseApiException { List attributes = classService.getAttributes(modelName, className); @@ -62,6 +65,7 @@ public ResponseEntity>> getAttributes( return ResponseEntity.ok(entityModels); } + @Operation(summary = "Get an attribute by name", description = "Returns a single attribute of the class") @GetMapping("/class/{className}/attribute/{attributeName}") public ResponseEntity> getAttributeByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String attributeName) throws UseApiException { AttributeDTO attribute = classService.getAttributeByName(modelName, className, attributeName); @@ -76,6 +80,7 @@ public ResponseEntity> getAttributeByName(@PathVariabl } + @Operation(summary = "List operations of a class", description = "Lists operations defined on the class") @GetMapping("/class/{className}/operations") public ResponseEntity>> getOperations(@PathVariable String modelName, @PathVariable String className) throws UseApiException { List operations = classService.getOperations(modelName, className); @@ -96,6 +101,7 @@ public ResponseEntity>> getOperations( return ResponseEntity.ok(entityModels); } + @Operation(summary = "Get an operation by name", description = "Returns a specific operation of the class") @GetMapping("/class/{className}/operation/{operationName}") public ResponseEntity> getOperationByName(@PathVariable String modelName, @PathVariable String className, @PathVariable String operationName) throws UseApiException { OperationDTO operation = classService.getOperationByName(modelName, className, operationName); @@ -112,6 +118,7 @@ public ResponseEntity> getOperationByName(@PathVariabl + @Operation(summary = "Add an attribute to a class", description = "Creates an attribute for the class") @PostMapping("/class/{className}/attribute") public ResponseEntity> addAttribute(@PathVariable String modelName, @PathVariable String className, @RequestBody AttributeDTO attributeDTO) throws UseApiException { AttributeDTO newAttribute = classService.createAttribute(modelName, className, attributeDTO); @@ -124,6 +131,7 @@ public ResponseEntity> addAttribute(@PathVariable Stri return new ResponseEntity<>(entityModels, HttpStatus.CREATED); } + @Operation(summary = "Add an operation to a class", description = "Creates an operation on the class") @PostMapping("/class/{className}/operation") public ResponseEntity> addOperation(@PathVariable String modelName, @PathVariable String className, @RequestBody OperationDTO operationDTO) throws UseApiException { OperationDTO newOperation = classService.createOperation(modelName, className, operationDTO); diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 85a4ff97a..93253599e 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -1,5 +1,6 @@ package org.tzi.use.rest.controller; +import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; @@ -21,15 +22,13 @@ @RequiredArgsConstructor public class ModelController { - // No need for @Autowired with @RequiredArgsConstructor - // because Lombok generates a constructor for final fields - // and Spring will use that constructor for dependency injection private final ModelService modelService; // ======================================== // GET Mappings // ======================================== + @Operation(summary = "Get a model by name", description = "Returns the requested model and related metadata") @GetMapping("/model/{modelName}") public ResponseEntity> getModelByName(@PathVariable String modelName) throws UseApiException { ModelDTO modelDTO = modelService.getModelByName(modelName); @@ -45,6 +44,7 @@ public ResponseEntity> getModelByName(@PathVariable String return new ResponseEntity<>(entityModel, HttpStatus.OK); } + @Operation(summary = "Get an association by model and name", description = "Returns a single association of the given model") @GetMapping("/model/{modelName}/association/{associationName}") public ResponseEntity> getModelAssociationByName(@PathVariable String modelName, @PathVariable String associationName) throws UseApiException { AssociationDTO association = modelService.getAssociationByName(modelName, associationName); @@ -58,6 +58,7 @@ public ResponseEntity> getModelAssociationByName(@Pa return new ResponseEntity<>(entityModel, HttpStatus.OK); } + @Operation(summary = "Get an invariant by model and name", description = "Returns a specific invariant of the model") @GetMapping("/model/{modelName}/invariant/{invariantName}") public ResponseEntity> getModelInvariantByName(@PathVariable String modelName, @PathVariable String invariantName) throws UseApiException { InvariantDTO invariant = modelService.getInvariantByName(modelName, invariantName); @@ -71,6 +72,7 @@ public ResponseEntity> getModelInvariantByName(@PathVa return new ResponseEntity<>(entityModel, HttpStatus.OK); } + @Operation(summary = "List all models", description = "Returns all available models with their metadata") @GetMapping("/models") public ResponseEntity>> getModels() throws UseApiException { List models = modelService.getAllModels(); @@ -96,6 +98,7 @@ public ResponseEntity>> getModels() throws } + @Operation(summary = "List all classes of a model", description = "Lists every class of the model") @GetMapping("/model/{modelName}/classes") public ResponseEntity getClasses(@PathVariable String modelName) throws UseApiException { List modelClasses = modelService.getModelClasses(modelName); @@ -120,6 +123,7 @@ public ResponseEntity getClasses(@PathVariable String modelName) throws UseAp } + @Operation(summary = "List all associations of a model", description = "Lists associations defined in the model") @GetMapping("/model/{modelName}/associations") public ResponseEntity>> getAssociations(@PathVariable String modelName) throws UseApiException { List associations = modelService.getModelAssociations(modelName); @@ -143,6 +147,7 @@ public ResponseEntity>> getAssociati } + @Operation(summary = "List all invariants of a model", description = "Lists invariants defined in the model") @GetMapping("/model/{modelName}/invariants") public ResponseEntity>> getInvariants(@PathVariable String modelName) throws UseApiException { List invariants = modelService.getModelInvariants(modelName); @@ -167,6 +172,7 @@ public ResponseEntity>> getInvariants( return new ResponseEntity<>(collectionModel, HttpStatus.OK); } + @Operation(summary = "List all pre/post conditions of a model", description = "Lists pre/post conditions defined in the model") @GetMapping("/model/{modelName}/prepostconditions") public ResponseEntity>> getPrePostConditions(@PathVariable String modelName) throws UseApiException { List prePostConditions = modelService.getModelPrePostConditions(modelName); @@ -190,6 +196,7 @@ public ResponseEntity>> getPreP return new ResponseEntity<>(collectionModel, HttpStatus.OK); } + @Operation(summary = "Get a pre/post condition by model and name", description = "Returns the named pre/post condition of the model") @GetMapping("/model/{modelName}/prepostcondition/{prePostConditionName}") public ResponseEntity> getModelPrePostCondByName(@PathVariable String modelName, @PathVariable String prePostConditionName) throws UseApiException { PrePostConditionDTO prePostCondition = modelService.getPrePostConditionByName(modelName, prePostConditionName); @@ -208,6 +215,7 @@ public ResponseEntity> getModelPrePostCondByNam // ======================================== + @Operation(summary = "Create a model", description = "Creates a new model") @PostMapping("/model") public ResponseEntity> createModel(@RequestBody ModelDTO modelDTO) throws UseApiException { ModelDTO createdModel = modelService.createModel(modelDTO); @@ -224,6 +232,7 @@ public ResponseEntity> createModel(@RequestBody ModelDTO m return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } + @Operation(summary = "Create a class in a model", description = "Adds a class to the given model") @PostMapping("/model/{modelName}/class") public ResponseEntity> createClass(@PathVariable String modelName, @RequestBody ClassDTO classDTO) throws UseApiException { ClassDTO createdClass = modelService.createClass(modelName, classDTO); @@ -240,6 +249,7 @@ public ResponseEntity> createClass(@PathVariable String mo return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } + @Operation(summary = "Create an association in a model", description = "Creates an association in the model") @PostMapping("/model/{modelName}/association") public ResponseEntity> createAssociation(@PathVariable String modelName, @RequestBody AssociationDTO association) throws UseApiException { AssociationDTO createdAssociation = modelService.createAssociation(modelName, association); @@ -254,6 +264,7 @@ public ResponseEntity> createAssociation(@PathVariab return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } + @Operation(summary = "Create an invariant in a class", description = "Adds an invariant scoped to a class within the model") @PostMapping("/model/{modelName}/{className}/invariant") public ResponseEntity> createInvariant(@PathVariable String modelName, @PathVariable String className, @RequestBody InvariantDTO invariantDTO) throws UseApiException { InvariantDTO createdInvariant = modelService.createInvariant(modelName, invariantDTO, className); @@ -268,6 +279,7 @@ public ResponseEntity> createInvariant(@PathVariable S return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } + @Operation(summary = "Create a pre/post condition in a class", description = "Adds a pre/post condition to a class") @PostMapping("/model/{modelName}/{className}/prepostcondition") public ResponseEntity> createPrePostCondition(@PathVariable String modelName, @PathVariable String className, @RequestBody PrePostConditionDTO prePostConditionDTO) throws UseApiException { PrePostConditionDTO createdPrePostCondition = modelService.createPrePostCondition(modelName, prePostConditionDTO, className); From a66ff6c7cec0a543cdbbc3baa24be5d35cbb4d55 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 09:41:06 +0100 Subject: [PATCH 133/148] removed todos and comments --- use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java | 4 +--- use-api/src/main/java/org/tzi/use/UseModelFacade.java | 1 - .../src/main/java/org/tzi/use/rest/services/ModelService.java | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java b/use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java index 0d47155c7..38025857b 100644 --- a/use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java +++ b/use-api/src/main/java/org/tzi/use/GlobalExceptionHandler.java @@ -14,9 +14,7 @@ import java.util.Map; /** - * Global exception handler for the REST API. - * This follows Spring Boot best practices for centralized exception handling. - * Extends ResponseEntityExceptionHandler to leverage Spring's built-in exception handling. + * Global exception handler for the REST API. Catches specific exceptions and returns appropriate HTTP responses. */ @ControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index f26d552e9..911623286 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -27,7 +27,6 @@ public void createClass(ModelNTT modelNTT, ClassNTT classNTT) throws UseApiExcep for (OperationNTT operation : classNTT.getOperations()) { uma.createOperation(classNTT.getName(), operation.getOperationName(), operation.getParameter(), operation.getReturnType()); } -// umaCache.put(modelNTT.getName(), uma); } public void createInvariant(ModelNTT modelNTT, InvariantNTT invariant, String className) throws UseApiException { diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 93a146474..3d3826ce1 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -47,7 +47,6 @@ public ClassDTO createClass(String modelName, ClassDTO classDTO) throws UseApiEx ModelNTT modelNTT = findModelByNameOrThrow(modelName); - //TODO doesnt uma already throw an error if class exists? boolean classExists = modelNTT.getClasses().stream().anyMatch(c -> c.getName().equals(classDTO.getName())); if (classExists) { throw new DuplicateKeyException("Class name already exists in model: " + modelName); From 34290c7fb28a7cbb2ad41aa49f4ab7d680c486ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:57:40 +0000 Subject: [PATCH 134/148] Initial plan From 3a6a4bd64ae94965364b1b009866c37d176e2935 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:07:38 +0000 Subject: [PATCH 135/148] Add delete methods for class, attribute, operation, association, prepostcondition, invariant and model Co-authored-by: husakki <81704101+husakki@users.noreply.github.com> --- .../use-webapi.postman_collection.json | 305 ++++++++++++++++++ .../main/java/org/tzi/use/UseModelFacade.java | 6 + .../use/rest/controller/ClassController.java | 15 + .../use/rest/controller/ModelController.java | 39 +++ .../tzi/use/rest/services/ClassService.java | 23 ++ .../tzi/use/rest/services/ModelService.java | 61 ++++ 6 files changed, 449 insertions(+) diff --git a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json index 84ea4e06e..74fdff445 100644 --- a/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json +++ b/use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json @@ -1031,6 +1031,311 @@ } } ] + }, + { + "name": "Delete Operations", + "item": [ + { + "name": "Delete Attribute - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute/email" + } + }, + { + "name": "Delete Attribute - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/attribute/nonExistentAttr" + } + }, + { + "name": "Delete Operation - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/operation/getInfo" + } + }, + { + "name": "Delete Operation - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/models/ComprehensiveTestModel/class/Person/operation/nonExistentOp" + } + }, + { + "name": "Delete PrePostCondition - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/prepostcondition/Person::getInfovalidPerson" + } + }, + { + "name": "Delete PrePostCondition - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/prepostcondition/nonExistent" + } + }, + { + "name": "Delete Invariant - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/invariant/Person" + } + }, + { + "name": "Delete Invariant - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/invariant/nonExistent" + } + }, + { + "name": "Delete Association - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/association/Person" + } + }, + { + "name": "Delete Association - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/association/nonExistent" + } + }, + { + "name": "Delete Class - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/class/Company" + } + }, + { + "name": "Delete Class - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel/class/nonExistent" + } + }, + { + "name": "Delete Model - Success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204 No Content', function () {", + " pm.response.to.have.status(204);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/ComprehensiveTestModel" + } + }, + { + "name": "Get Model After Delete - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "url": "localhost:8080/api/model/ComprehensiveTestModel" + } + }, + { + "name": "Delete Model - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 400 Bad Request', function () {", + " pm.response.to.have.status(400);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "url": "localhost:8080/api/model/NonExistentModel" + } + } + ] } ] } \ No newline at end of file diff --git a/use-api/src/main/java/org/tzi/use/UseModelFacade.java b/use-api/src/main/java/org/tzi/use/UseModelFacade.java index 911623286..11720a3e8 100644 --- a/use-api/src/main/java/org/tzi/use/UseModelFacade.java +++ b/use-api/src/main/java/org/tzi/use/UseModelFacade.java @@ -65,6 +65,12 @@ public void createPrePostCondition(ModelNTT modelNTT, PrePostConditionNTT ppc, S } + /* Delete */ + + public void deleteModel(String modelName) { + umaCache.remove(modelName); + } + /* Helper Methods */ private static String extractClassName(String concatenatedClassName) { diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java index 8d4af4ad3..f3ee5e2fd 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ClassController.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -143,4 +144,18 @@ public ResponseEntity> addOperation(@PathVariable Stri return new ResponseEntity<>(entityModels, HttpStatus.CREATED); } + + @Operation(summary = "Delete an attribute from a class", description = "Deletes the attribute from the class") + @DeleteMapping("/class/{className}/attribute/{attributeName}") + public ResponseEntity deleteAttribute(@PathVariable String modelName, @PathVariable String className, @PathVariable String attributeName) { + classService.deleteAttribute(modelName, className, attributeName); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "Delete an operation from a class", description = "Deletes the operation from the class") + @DeleteMapping("/class/{className}/operation/{operationName}") + public ResponseEntity deleteOperation(@PathVariable String modelName, @PathVariable String className, @PathVariable String operationName) { + classService.deleteOperation(modelName, className, operationName); + return ResponseEntity.noContent().build(); + } } diff --git a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java index 93253599e..efe98212a 100644 --- a/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java +++ b/use-api/src/main/java/org/tzi/use/rest/controller/ModelController.java @@ -293,4 +293,43 @@ public ResponseEntity> createPrePostCondition(@ return new ResponseEntity<>(entityModel, HttpStatus.CREATED); } + + // ======================================== + // DELETE Mappings + // ======================================== + + @Operation(summary = "Delete a model", description = "Deletes the model and all its classes, associations, invariants and prepostconditions") + @DeleteMapping("/model/{modelName}") + public ResponseEntity deleteModel(@PathVariable String modelName) { + modelService.deleteModel(modelName); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "Delete a class from a model", description = "Deletes the class and its attributes, operations and associations referencing it") + @DeleteMapping("/model/{modelName}/class/{className}") + public ResponseEntity deleteClass(@PathVariable String modelName, @PathVariable String className) { + modelService.deleteClass(modelName, className); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "Delete an association from a model", description = "Deletes the association from the model") + @DeleteMapping("/model/{modelName}/association/{associationName}") + public ResponseEntity deleteAssociation(@PathVariable String modelName, @PathVariable String associationName) { + modelService.deleteAssociation(modelName, associationName); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "Delete an invariant from a model", description = "Deletes the invariant from the model") + @DeleteMapping("/model/{modelName}/invariant/{invariantName}") + public ResponseEntity deleteInvariant(@PathVariable String modelName, @PathVariable String invariantName) { + modelService.deleteInvariant(modelName, invariantName); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "Delete a pre/post condition from a model", description = "Deletes the pre/post condition from the model") + @DeleteMapping("/model/{modelName}/prepostcondition/{prePostConditionName}") + public ResponseEntity deletePrePostCondition(@PathVariable String modelName, @PathVariable String prePostConditionName) { + modelService.deletePrePostCondition(modelName, prePostConditionName); + return ResponseEntity.noContent().build(); + } } diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java index f4a912857..798dc5747 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ClassService.java @@ -84,6 +84,29 @@ public AttributeDTO getAttributeByName(String modelName, String className, Strin .orElseThrow(() -> new IllegalArgumentException("Attribute not found: " + attributeName)); } + /* Delete */ + public void deleteAttribute(String modelName, String className, String attributeName) { + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); + + boolean removed = classNTT.getAttributes().removeIf(attr -> attr.getName().equals(attributeName)); + if (!removed) { + throw new IllegalArgumentException("Attribute not found: " + attributeName); + } + modelRepo.save(modelNTT); + } + + public void deleteOperation(String modelName, String className, String operationName) { + ModelNTT modelNTT = modelService.findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); + + boolean removed = classNTT.getOperations().removeIf(op -> op.getOperationName().equals(operationName)); + if (!removed) { + throw new IllegalArgumentException("Operation not found: " + operationName); + } + modelRepo.save(modelNTT); + } + /* Helper Methods */ private ClassNTT findClassByNameOrThrow(ModelNTT modelNTT, String className) { return modelNTT.getClasses().stream() diff --git a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java index 3d3826ce1..d039ea74e 100644 --- a/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java +++ b/use-api/src/main/java/org/tzi/use/rest/services/ModelService.java @@ -140,9 +140,70 @@ public PrePostConditionDTO getPrePostConditionByName(String modelName, String pr return prePostConditionMapper.toDTO(prePostConditionNTT); } + /* Delete */ + + // Recursively deletes model with all its classes, associations, invariants and prepostconditions + public void deleteModel(String modelName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + modelNTT.getClasses().clear(); + modelNTT.getAssociations().clear(); + modelNTT.getInvariants().clear(); + modelNTT.getPrePostConditions().clear(); + useModelFacade.deleteModel(modelName); + modelRepo.delete(modelNTT); + } + + // Recursively deletes class with its attributes, operations and associations referencing the class + public void deleteClass(String modelName, String className) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + ClassNTT classNTT = findClassByNameOrThrow(modelNTT, className); + + classNTT.getAttributes().clear(); + classNTT.getOperations().clear(); + + modelNTT.getAssociations().entrySet().removeIf(entry -> { + AssociationNTT assoc = entry.getValue(); + return assoc.getEnd1ClassName().equals(className) || assoc.getEnd2ClassName().equals(className); + }); + + modelNTT.getClasses().remove(classNTT); + modelRepo.save(modelNTT); + } + + public void deleteAssociation(String modelName, String associationName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + if (modelNTT.getAssociations().remove(associationName) == null) { + throw new IllegalArgumentException("Association not found: " + associationName); + } + modelRepo.save(modelNTT); + } + + public void deleteInvariant(String modelName, String invariantName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + if (modelNTT.getInvariants().remove(invariantName) == null) { + throw new IllegalArgumentException("Invariant not found: " + invariantName); + } + modelRepo.save(modelNTT); + } + + public void deletePrePostCondition(String modelName, String prePostConditionName) { + ModelNTT modelNTT = findModelByNameOrThrow(modelName); + if (modelNTT.getPrePostConditions().remove(prePostConditionName) == null) { + throw new IllegalArgumentException("PrePostCondition not found: " + prePostConditionName); + } + modelRepo.save(modelNTT); + } + /* Helper Methods */ ModelNTT findModelByNameOrThrow(String modelName) { return modelRepo.findById(modelName).orElseThrow(() -> new IllegalArgumentException("Model not found: " + modelName)); } + private ClassNTT findClassByNameOrThrow(ModelNTT modelNTT, String className) { + return modelNTT.getClasses().stream() + .filter(c -> c.getName().equals(className)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Class not found: " + className)); + } + } From 0800de02cd404fbcf949d0fdb0d2fa06c0d27a66 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:35:36 +0100 Subject: [PATCH 136/148] removed hardcoded creds --- .github/workflows/maven.yml | 6 +++++- .gitignore | 1 + use-api/.env.example | 5 +++++ use-api/docker-compose.yml | 16 ++++++++++------ .../src/main/resources/application.properties | 10 +++++----- 5 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 use-api/.env.example diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9b688fabb..ebbca5819 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -103,8 +103,12 @@ jobs: run: mkdir target && cp use-api-7.1.1.jar target - name: Run docker compose - #run: docker compose up -d --wait run: docker compose up -d --wait + env: + MONGODB_USERNAME: ${{ secrets.MONGODB_USERNAME }} + MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} + MONGODB_DATABASE: ${{ secrets.MONGODB_DATABASE }} + MONGODB_HOST: mongodb_cicd - name: Wait for docker to be ready diff --git a/.gitignore b/.gitignore index 03bbe636e..4cd4fa805 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,4 @@ fabric.properties **/.DS_Store /.idea /use-api/target +use-api/.env \ No newline at end of file diff --git a/use-api/.env.example b/use-api/.env.example new file mode 100644 index 000000000..d9a26a940 --- /dev/null +++ b/use-api/.env.example @@ -0,0 +1,5 @@ +MONGODB_USERNAME=your_username +MONGODB_PASSWORD=your_password +MONGODB_DATABASE=use-database +MONGODB_PORT=27017 +MONGODB_HOST=localhost \ No newline at end of file diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index 1f5f27363..cb252f29f 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -9,9 +9,9 @@ services: volumes: - mongodb_data:/data/db environment: - - MONGO_INITDB_ROOT_USERNAME=rootuser - - MONGO_INITDB_ROOT_PASSWORD=rootpass - - MONGO_INITDB_DATABASE=use-database + - MONGO_INITDB_ROOT_USERNAME=${MONGODB_USERNAME:-rootuser} + - MONGO_INITDB_ROOT_PASSWORD=${MONGODB_PASSWORD:-rootpass} + - MONGO_INITDB_DATABASE=${MONGODB_DATABASE:-use-database} use-api: build: . @@ -21,13 +21,17 @@ services: depends_on: - mongodb environment: - - SPRING_DATA_MONGODB_HOST=mongodb_cicd + - SPRING_DATA_MONGODB_HOST=${MONGODB_HOST:-mongodb_cicd} + - MONGODB_USERNAME=${MONGODB_USERNAME:-rootuser} + - MONGODB_PASSWORD=${MONGODB_PASSWORD:-rootpass} + - MONGODB_DATABASE=${MONGODB_DATABASE:-use-database} + - MONGODB_PORT=27017 healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] # Or /actuator/health if using Spring Actuator + test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] interval: 5s timeout: 5s retries: 10 - start_period: 40s + start_period: 30s volumes: mongodb_data: diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index f3dbe100d..a0183d831 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -13,11 +13,11 @@ springdoc.swagger-ui.filter=true # mongoDB connection spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=rootuser -spring.data.mongodb.password=rootpass -spring.data.mongodb.database=use-database -spring.data.mongodb.port=27017 -spring.data.mongodb.host=localhost +spring.data.mongodb.username=${MONGODB_USERNAME} +spring.data. mongodb.password=${MONGODB_PASSWORD} +spring.data.mongodb.database=${MONGODB_DATABASE} +spring.data.mongodb. port=${MONGODB_PORT} +spring.data.mongodb.host=${MONGODB_HOST} # Actuator configuration management.endpoints.web.exposure.include=health From c79a98f17d53fdf13eb318b82a55d36ea374c07c Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:40:58 +0100 Subject: [PATCH 137/148] 40s period --- use-api/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index cb252f29f..9952dcfa7 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -31,7 +31,7 @@ services: interval: 5s timeout: 5s retries: 10 - start_period: 30s + start_period: 40s volumes: mongodb_data: From 6e3a20d2addb0e0c041a40dc6288e243f43cfddc Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:47:56 +0100 Subject: [PATCH 138/148] default values --- use-api/src/main/resources/application.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index a0183d831..dedecb3d8 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -13,11 +13,11 @@ springdoc.swagger-ui.filter=true # mongoDB connection spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=${MONGODB_USERNAME} -spring.data. mongodb.password=${MONGODB_PASSWORD} -spring.data.mongodb.database=${MONGODB_DATABASE} -spring.data.mongodb. port=${MONGODB_PORT} -spring.data.mongodb.host=${MONGODB_HOST} +spring.data.mongodb.username=${MONGODB_USERNAME: rootuser} +spring.data. mongodb.password=${MONGODB_PASSWORD:rootpass} +spring.data.mongodb.database=${MONGODB_DATABASE:use-database} +spring.data.mongodb. port=${MONGODB_PORT:27017} +spring.data.mongodb.host=${MONGODB_HOST:localhost} # Actuator configuration management.endpoints.web.exposure.include=health From 9e682d8d3ca8c80044e911a895c5ef1c98db7cbc Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:54:07 +0100 Subject: [PATCH 139/148] Revert "default values" This reverts commit 0899b77dfec7628dbc3002cb1d98abb0c97caeae. --- use-api/src/main/resources/application.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index dedecb3d8..a0183d831 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -13,11 +13,11 @@ springdoc.swagger-ui.filter=true # mongoDB connection spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=${MONGODB_USERNAME: rootuser} -spring.data. mongodb.password=${MONGODB_PASSWORD:rootpass} -spring.data.mongodb.database=${MONGODB_DATABASE:use-database} -spring.data.mongodb. port=${MONGODB_PORT:27017} -spring.data.mongodb.host=${MONGODB_HOST:localhost} +spring.data.mongodb.username=${MONGODB_USERNAME} +spring.data. mongodb.password=${MONGODB_PASSWORD} +spring.data.mongodb.database=${MONGODB_DATABASE} +spring.data.mongodb. port=${MONGODB_PORT} +spring.data.mongodb.host=${MONGODB_HOST} # Actuator configuration management.endpoints.web.exposure.include=health From 9151479e35e302d5f4112e8be13a182dd7898df9 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:54:13 +0100 Subject: [PATCH 140/148] Revert "40s period" This reverts commit 7568d591cadf8981c8d4b5f9908d46e28a134186. --- use-api/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index 9952dcfa7..cb252f29f 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -31,7 +31,7 @@ services: interval: 5s timeout: 5s retries: 10 - start_period: 40s + start_period: 30s volumes: mongodb_data: From efb8c0f6e20de8a316c459dbc51452126b9905bc Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:54:16 +0100 Subject: [PATCH 141/148] Revert "removed hardcoded creds" This reverts commit 0975aecba4d049aed92fb909daee860615bc927a. --- .github/workflows/maven.yml | 6 +----- .gitignore | 1 - use-api/.env.example | 5 ----- use-api/docker-compose.yml | 16 ++++++---------- .../src/main/resources/application.properties | 10 +++++----- 5 files changed, 12 insertions(+), 26 deletions(-) delete mode 100644 use-api/.env.example diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ebbca5819..9b688fabb 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -103,12 +103,8 @@ jobs: run: mkdir target && cp use-api-7.1.1.jar target - name: Run docker compose + #run: docker compose up -d --wait run: docker compose up -d --wait - env: - MONGODB_USERNAME: ${{ secrets.MONGODB_USERNAME }} - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - MONGODB_DATABASE: ${{ secrets.MONGODB_DATABASE }} - MONGODB_HOST: mongodb_cicd - name: Wait for docker to be ready diff --git a/.gitignore b/.gitignore index 4cd4fa805..03bbe636e 100644 --- a/.gitignore +++ b/.gitignore @@ -119,4 +119,3 @@ fabric.properties **/.DS_Store /.idea /use-api/target -use-api/.env \ No newline at end of file diff --git a/use-api/.env.example b/use-api/.env.example deleted file mode 100644 index d9a26a940..000000000 --- a/use-api/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -MONGODB_USERNAME=your_username -MONGODB_PASSWORD=your_password -MONGODB_DATABASE=use-database -MONGODB_PORT=27017 -MONGODB_HOST=localhost \ No newline at end of file diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index cb252f29f..1f5f27363 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -9,9 +9,9 @@ services: volumes: - mongodb_data:/data/db environment: - - MONGO_INITDB_ROOT_USERNAME=${MONGODB_USERNAME:-rootuser} - - MONGO_INITDB_ROOT_PASSWORD=${MONGODB_PASSWORD:-rootpass} - - MONGO_INITDB_DATABASE=${MONGODB_DATABASE:-use-database} + - MONGO_INITDB_ROOT_USERNAME=rootuser + - MONGO_INITDB_ROOT_PASSWORD=rootpass + - MONGO_INITDB_DATABASE=use-database use-api: build: . @@ -21,17 +21,13 @@ services: depends_on: - mongodb environment: - - SPRING_DATA_MONGODB_HOST=${MONGODB_HOST:-mongodb_cicd} - - MONGODB_USERNAME=${MONGODB_USERNAME:-rootuser} - - MONGODB_PASSWORD=${MONGODB_PASSWORD:-rootpass} - - MONGODB_DATABASE=${MONGODB_DATABASE:-use-database} - - MONGODB_PORT=27017 + - SPRING_DATA_MONGODB_HOST=mongodb_cicd healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] + test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] # Or /actuator/health if using Spring Actuator interval: 5s timeout: 5s retries: 10 - start_period: 30s + start_period: 40s volumes: mongodb_data: diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index a0183d831..f3dbe100d 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -13,11 +13,11 @@ springdoc.swagger-ui.filter=true # mongoDB connection spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=${MONGODB_USERNAME} -spring.data. mongodb.password=${MONGODB_PASSWORD} -spring.data.mongodb.database=${MONGODB_DATABASE} -spring.data.mongodb. port=${MONGODB_PORT} -spring.data.mongodb.host=${MONGODB_HOST} +spring.data.mongodb.username=rootuser +spring.data.mongodb.password=rootpass +spring.data.mongodb.database=use-database +spring.data.mongodb.port=27017 +spring.data.mongodb.host=localhost # Actuator configuration management.endpoints.web.exposure.include=health From 8a4257e81b66d757f17dd690d256d8ef59ef209e Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 22:58:36 +0100 Subject: [PATCH 142/148] Reapply "removed hardcoded creds" This reverts commit a8fd95df8f0d93ad17a6b6936e94aa0482369423. --- .github/workflows/maven.yml | 6 +++++- .gitignore | 1 + use-api/.env.example | 5 +++++ use-api/docker-compose.yml | 16 ++++++++++------ .../src/main/resources/application.properties | 10 +++++----- 5 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 use-api/.env.example diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9b688fabb..ebbca5819 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -103,8 +103,12 @@ jobs: run: mkdir target && cp use-api-7.1.1.jar target - name: Run docker compose - #run: docker compose up -d --wait run: docker compose up -d --wait + env: + MONGODB_USERNAME: ${{ secrets.MONGODB_USERNAME }} + MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} + MONGODB_DATABASE: ${{ secrets.MONGODB_DATABASE }} + MONGODB_HOST: mongodb_cicd - name: Wait for docker to be ready diff --git a/.gitignore b/.gitignore index 03bbe636e..4cd4fa805 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,4 @@ fabric.properties **/.DS_Store /.idea /use-api/target +use-api/.env \ No newline at end of file diff --git a/use-api/.env.example b/use-api/.env.example new file mode 100644 index 000000000..d9a26a940 --- /dev/null +++ b/use-api/.env.example @@ -0,0 +1,5 @@ +MONGODB_USERNAME=your_username +MONGODB_PASSWORD=your_password +MONGODB_DATABASE=use-database +MONGODB_PORT=27017 +MONGODB_HOST=localhost \ No newline at end of file diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index 1f5f27363..cb252f29f 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -9,9 +9,9 @@ services: volumes: - mongodb_data:/data/db environment: - - MONGO_INITDB_ROOT_USERNAME=rootuser - - MONGO_INITDB_ROOT_PASSWORD=rootpass - - MONGO_INITDB_DATABASE=use-database + - MONGO_INITDB_ROOT_USERNAME=${MONGODB_USERNAME:-rootuser} + - MONGO_INITDB_ROOT_PASSWORD=${MONGODB_PASSWORD:-rootpass} + - MONGO_INITDB_DATABASE=${MONGODB_DATABASE:-use-database} use-api: build: . @@ -21,13 +21,17 @@ services: depends_on: - mongodb environment: - - SPRING_DATA_MONGODB_HOST=mongodb_cicd + - SPRING_DATA_MONGODB_HOST=${MONGODB_HOST:-mongodb_cicd} + - MONGODB_USERNAME=${MONGODB_USERNAME:-rootuser} + - MONGODB_PASSWORD=${MONGODB_PASSWORD:-rootpass} + - MONGODB_DATABASE=${MONGODB_DATABASE:-use-database} + - MONGODB_PORT=27017 healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] # Or /actuator/health if using Spring Actuator + test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] interval: 5s timeout: 5s retries: 10 - start_period: 40s + start_period: 30s volumes: mongodb_data: diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index f3dbe100d..a0183d831 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -13,11 +13,11 @@ springdoc.swagger-ui.filter=true # mongoDB connection spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=rootuser -spring.data.mongodb.password=rootpass -spring.data.mongodb.database=use-database -spring.data.mongodb.port=27017 -spring.data.mongodb.host=localhost +spring.data.mongodb.username=${MONGODB_USERNAME} +spring.data. mongodb.password=${MONGODB_PASSWORD} +spring.data.mongodb.database=${MONGODB_DATABASE} +spring.data.mongodb. port=${MONGODB_PORT} +spring.data.mongodb.host=${MONGODB_HOST} # Actuator configuration management.endpoints.web.exposure.include=health From 38cdbcf825962edcce1ae238657d4d5f449ee7bf Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 23:14:01 +0100 Subject: [PATCH 143/148] fixed errors, some extra spaces and wrong var names --- use-api/docker-compose.yml | 8 ++++---- use-api/src/main/resources/application.properties | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index cb252f29f..c5a4efc37 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -22,10 +22,10 @@ services: - mongodb environment: - SPRING_DATA_MONGODB_HOST=${MONGODB_HOST:-mongodb_cicd} - - MONGODB_USERNAME=${MONGODB_USERNAME:-rootuser} - - MONGODB_PASSWORD=${MONGODB_PASSWORD:-rootpass} - - MONGODB_DATABASE=${MONGODB_DATABASE:-use-database} - - MONGODB_PORT=27017 + - SPRING_DATA_MONGODB_PORT=${MONGODB_PORT:27017} + - SPRING_DATA_MONGODB_USERNAME=${MONGODB_USERNAME:-rootuser} + - SPRING_DATA_MONGODB_PASSWORD=${MONGODB_PASSWORD:-rootpass} + - SPRING_DATA_MONGODB_DATABASE=${MONGODB_DATABASE:-use-database} healthcheck: test: [ "CMD", "curl", "-f", "http://localhost:8080/actuator/health" ] interval: 5s diff --git a/use-api/src/main/resources/application.properties b/use-api/src/main/resources/application.properties index a0183d831..cdb952633 100644 --- a/use-api/src/main/resources/application.properties +++ b/use-api/src/main/resources/application.properties @@ -13,11 +13,11 @@ springdoc.swagger-ui.filter=true # mongoDB connection spring.data.mongodb.authentication-database=admin -spring.data.mongodb.username=${MONGODB_USERNAME} -spring.data. mongodb.password=${MONGODB_PASSWORD} -spring.data.mongodb.database=${MONGODB_DATABASE} -spring.data.mongodb. port=${MONGODB_PORT} -spring.data.mongodb.host=${MONGODB_HOST} +spring.data.mongodb.username=${MONGODB_USERNAME:rootuser} +spring.data.mongodb.password=${MONGODB_PASSWORD:rootpass} +spring.data.mongodb.database=${MONGODB_DATABASE:use-database} +spring.data.mongodb.port=${MONGODB_PORT:27017} +spring.data.mongodb.host=${MONGODB_HOST:localhost} # Actuator configuration management.endpoints.web.exposure.include=health From 1123d92cae0d7c963ef07ed3e2f5ee815e7109e8 Mon Sep 17 00:00:00 2001 From: husakki Date: Thu, 18 Dec 2025 23:18:27 +0100 Subject: [PATCH 144/148] Need to escape any $ with another $. --- use-api/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/docker-compose.yml b/use-api/docker-compose.yml index c5a4efc37..2083f6602 100644 --- a/use-api/docker-compose.yml +++ b/use-api/docker-compose.yml @@ -22,7 +22,7 @@ services: - mongodb environment: - SPRING_DATA_MONGODB_HOST=${MONGODB_HOST:-mongodb_cicd} - - SPRING_DATA_MONGODB_PORT=${MONGODB_PORT:27017} + - SPRING_DATA_MONGODB_PORT=${MONGODB_PORT:-27017} - SPRING_DATA_MONGODB_USERNAME=${MONGODB_USERNAME:-rootuser} - SPRING_DATA_MONGODB_PASSWORD=${MONGODB_PASSWORD:-rootpass} - SPRING_DATA_MONGODB_DATABASE=${MONGODB_DATABASE:-use-database} From 3f9eb59c74ab961cd098c7b15d662243d87bd412 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 19 Dec 2025 14:26:39 +0100 Subject: [PATCH 145/148] fixed the syntax and merged the code correctly --- .github/workflows/maven.yml | 191 +++++++++++++++++------------------- 1 file changed, 89 insertions(+), 102 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ebbca5819..eb06eaeb4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,53 +1,9 @@ -# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - name: Java CI with Maven -on: - push +on: push jobs: build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up JDK - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'adopt' - cache: maven - - name: Build with Maven - run: | - start_time=$(date +%s) - mvn --batch-mode --update-snapshots verify | tee build_output.log - end_time=$(date +%s) - build_time=$((end_time - start_time)) - echo "BUILD_TIME_SECONDS=$build_time" >> build_output.log - run: mvn --batch-mode --update-snapshots verify - - name: Upload build result use-assembly - run: mkdir staging && cp use-assembly/target/*.zip staging - - uses: actions/upload-artifact@v4 - with: - name: Package - path: staging - - uses: actions/upload-artifact@v4 - with: - name: build-log - path: build_output.log - - uses: actions/upload-artifact@v4 - with: - name: failure-reports - path: | - docs/archunit-results/cycles-current-failure-report.txt - docs/archunit-results/layers-current-failure-report.txt - - - name: Upload build result use-api - run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase - - uses: actions/upload-artifact@v4 - with: - name: constructed_use-api - path: testphase - uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v4 @@ -55,20 +11,51 @@ jobs: java-version: '21' distribution: 'adopt' cache: maven + - name: Build with Maven + run: | + start_time=$(date +%s) + mvn --batch-mode --update-snapshots verify | tee build_output.log + end_time=$(date +%s) + build_time=$((end_time - start_time)) + echo "BUILD_TIME_SECONDS=$build_time" >> build_output.log + + - name: Upload build result + run: mkdir staging && cp use-assembly/target/*.zip staging + - uses: actions/upload-artifact@v4 + with: + name: Package + path: staging + - uses: actions/upload-artifact@v4 + with: + name: build-log + path: build_output.log + - uses: actions/upload-artifact@v4 + with: + name: failure-reports + path: | + docs/archunit-results/cycles-current-failure-report.txt + docs/archunit-results/layers-current-failure-report.txt + + - name: Upload build result use-api + run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase + - uses: actions/upload-artifact@v4 + with: + name: constructed_use-api + path: testphase - - name: Upload postman tests - run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests - - uses: actions/upload-artifact@v4 - with: - name: postman_tests - path: postmantests + - name: Upload postman tests + run: mkdir postmantests && cp use-api/src/it/java/org.tzi.use/postman_collection/use-webapi.postman_collection.json postmantests + - uses: actions/upload-artifact@v4 + with: + name: postman_tests + path: postmantests - - name: Upload docker image - run: mkdir docker && cp use-api/docker-compose.yml docker && cp use-api/Dockerfile docker - - uses: actions/upload-artifact@v4 - with: - name: docker_image - path: docker + - name: Upload docker image + run: mkdir docker && cp use-api/docker-compose.yml docker && cp use-api/Dockerfile docker + - uses: actions/upload-artifact@v4 + with: + name: docker_image + path: docker @@ -77,48 +64,48 @@ jobs: runs-on: ubuntu-latest steps: - - name: Set up Java - uses: actions/setup-java@v3 - with: - java-version: '21' - distribution: 'adopt' - - - - name: Download Artifact use-api jar - uses: actions/download-artifact@v4 - with: - name: constructed_use-api - - - name: Download Artifact postman tests - uses: actions/download-artifact@v4 - with: - name: postman_tests - - - name: Download Aritfact Dockerimage - uses: actions/download-artifact@v4 - with: - name: docker_image - - - name: move the jar - run: mkdir target && cp use-api-7.1.1.jar target - - - name: Run docker compose - run: docker compose up -d --wait - env: - MONGODB_USERNAME: ${{ secrets.MONGODB_USERNAME }} - MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} - MONGODB_DATABASE: ${{ secrets.MONGODB_DATABASE }} - MONGODB_HOST: mongodb_cicd - - - - name: Wait for docker to be ready - run: sleep 20 - - - name: Run Postman tests - run: | - npm install -g newman - newman run use-webapi.postman_collection.json - - - name: Stop services - if: always() - run: docker compose down + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'adopt' + + + - name: Download Artifact use-api jar + uses: actions/download-artifact@v4 + with: + name: constructed_use-api + + - name: Download Artifact postman tests + uses: actions/download-artifact@v4 + with: + name: postman_tests + + - name: Download Aritfact Dockerimage + uses: actions/download-artifact@v4 + with: + name: docker_image + + - name: move the jar + run: mkdir target && cp use-api-7.1.1.jar target + + - name: Run docker compose + run: docker compose up -d --wait + env: + MONGODB_USERNAME: ${{ secrets.MONGODB_USERNAME }} + MONGODB_PASSWORD: ${{ secrets.MONGODB_PASSWORD }} + MONGODB_DATABASE: ${{ secrets.MONGODB_DATABASE }} + MONGODB_HOST: mongodb_cicd + + + - name: Wait for docker to be ready + run: sleep 20 + + - name: Run Postman tests + run: | + npm install -g newman + newman run use-webapi.postman_collection.json + + - name: Stop services + if: always() + run: docker compose down From b3b72acae9556f1c1cec4db29377bc9b723460ec Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 19 Dec 2025 14:41:29 +0100 Subject: [PATCH 146/148] added use-api module --- .github/workflows/maven.yml | 6 +++--- pom.xml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index eb06eaeb4..f93ed0507 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,5 +1,6 @@ name: Java CI with Maven -on: push +on: + push jobs: build: runs-on: ubuntu-latest @@ -18,7 +19,6 @@ jobs: end_time=$(date +%s) build_time=$((end_time - start_time)) echo "BUILD_TIME_SECONDS=$build_time" >> build_output.log - - name: Upload build result run: mkdir staging && cp use-assembly/target/*.zip staging - uses: actions/upload-artifact@v4 @@ -35,7 +35,7 @@ jobs: path: | docs/archunit-results/cycles-current-failure-report.txt docs/archunit-results/layers-current-failure-report.txt - + - name: Upload build result use-api run: mkdir testphase && cp use-api/target/use-api-7.1.1.jar testphase - uses: actions/upload-artifact@v4 diff --git a/pom.xml b/pom.xml index 16a851563..bfeadb9ec 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ use-assembly use-core use-gui + use-api From 50731fd10bd0396a55e6a2ce4d176c7fbfcac479 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 19 Dec 2025 14:42:16 +0100 Subject: [PATCH 147/148] Update encodings.xml --- .idea/encodings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 882bb50c6..27b0cfc26 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -3,6 +3,8 @@ + + From eb38b4fec9a9fde1a928e9d3bfd12fa6dd0fab69 Mon Sep 17 00:00:00 2001 From: husakki Date: Fri, 19 Dec 2025 14:56:01 +0100 Subject: [PATCH 148/148] update use-api use version to 7.5.0 --- use-api/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/use-api/pom.xml b/use-api/pom.xml index 55da9509e..b16598b15 100644 --- a/use-api/pom.xml +++ b/use-api/pom.xml @@ -5,7 +5,7 @@ use org.tzi.use - 7.1.1 + 7.5.0 4.0.0