diff --git a/plugins/backend-application-default/README.md b/plugins/backend-application-default/README.md index 8249a8d6..703bef6a 100644 --- a/plugins/backend-application-default/README.md +++ b/plugins/backend-application-default/README.md @@ -7,24 +7,25 @@ Visit https://zenwave360.github.io/docs/zenwave-sdk/backend-application for comp ## Options -| **Option** | **Description** | **Type** | **Default** | **Values** | -|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|------------------|-------------------------|-----------------------------------| -| `specFile` | Spec file to parse | String | | | -| `targetFolder` | Target folder to generate code to. If left empty, it will print to stdout. | File | | | -| `specFiles` | ZDL files to parse | String[] | [] | | -| `basePackage` | Java Models package name | String | io.example.domain.model | | -| `persistence` | Persistence | PersistenceType | mongodb | mongodb, jpa | -| `style` | Programming Style | ProgrammingStyle | imperative | imperative, reactive | -| `databaseType` | SQL database flavor | DatabaseType | postgresql | postgresql, mariadb | -| `idJavaType` | Specifies the Java data type for the ID fields of entities. Defaults to Long for JPA and String for MongoDB if not explicitly set. | String | | | -| `useLombok` | Use @Getter and @Setter annotations from Lombok | boolean | false | | -| `inputDTOSuffix` | If not empty, it will generate (and use) an `input` DTO for each entity used as command parameter | String | | | -| `includeEmitEventsImplementation` | Whether to add IEntityEventProducer interfaces as service dependencies. Depends on the naming convention of zenwave-asyncapi plugin to work. | boolean | false | | -| `entities` | Entities to generate code for | List | [] | | -| `formatter` | Code formatter implementation | Formatters | spring | google, palantir, spring, eclipse | -| `skipFormatting` | Skip java sources output formatting | boolean | false | | -| `continueOnZdlError` | Continue even when ZDL contains fatal errors | boolean | true | | -| `haltOnFailFormatting` | Halt on formatting errors | boolean | true | | +| **Option** | **Description** | **Type** | **Default** | **Values** | +|-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|-------------------------|-----------------------------------| +| `specFile` | Spec file to parse | String | | | +| `targetFolder` | Target folder to generate code to. If left empty, it will print to stdout. | File | | | +| `specFiles` | ZDL files to parse | String[] | [] | | +| `basePackage` | Java Models package name | String | io.example.domain.model | | +| `persistence` | Persistence | PersistenceType | mongodb | mongodb, jpa | +| `style` | Programming Style | ProgrammingStyle | imperative | imperative, reactive | +| `databaseType` | SQL database flavor | DatabaseType | postgresql | postgresql, mariadb | +| `idJavaType` | Specifies the Java data type for the ID fields of entities. Defaults to Long for JPA and String for MongoDB if not explicitly set. | String | | | +| `useLombok` | Use @Getter and @Setter annotations from Lombok | boolean | false | | +| `inputDTOSuffix` | If not empty, it will generate (and use) an `input` DTO for each entity used as command parameter | String | | | +| `includeEmitEventsImplementation` | Whether to add IEntityEventProducer interfaces as service dependencies. Depends on the naming convention of zenwave-asyncapi plugin to work. | boolean | false | | +| `addRelationshipsById` | Controls whether to add a read/write relationship by id when mapping relationships between aggregate (not recommended) keeping the relationship by object readonly. | boolean | false | | +| `entities` | Entities to generate code for | List | [] | | +| `formatter` | Code formatter implementation | Formatters | spring | google, palantir, spring, eclipse | +| `skipFormatting` | Skip java sources output formatting | boolean | false | | +| `continueOnZdlError` | Continue even when ZDL contains fatal errors | boolean | true | | +| `haltOnFailFormatting` | Halt on formatting errors | boolean | true | | ## Getting Help diff --git a/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendApplicationDefaultJpaHelpers.java b/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendApplicationDefaultJpaHelpers.java index 39cd042b..bab510f1 100644 --- a/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendApplicationDefaultJpaHelpers.java +++ b/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendApplicationDefaultJpaHelpers.java @@ -20,14 +20,18 @@ public class BackendApplicationDefaultJpaHelpers { } public Boolean addRelationshipById(Object relationship, Options options) { + if (!generator.addRelationshipsById) { + return false; + } var zdl = options.get("zdl"); String entityName = JSONPath.get(relationship, "entityName"); String otherEntityName = JSONPath.get(relationship, "otherEntityName"); boolean isAggregate = JSONPath.get(zdl, String.format("entities.%s.options.aggregate", entityName), false); boolean isOtherEntityAggregate = JSONPath.get(zdl, String.format("entities.%s.options.aggregate", otherEntityName), false); boolean isOwnerSide = JSONPath.get(relationship, "ownerSide", false); + boolean isMapsIdParent = JSONPath.get(relationship, "isMapsIdParent", false); String relationType = JSONPath.get(relationship, "type"); - return ("OneToOne".contentEquals(relationType) || "ManyToOne".contentEquals(relationType)) && isOwnerSide && isAggregate && isOtherEntityAggregate; + return (("OneToOne".contentEquals(relationType) && !isMapsIdParent) || "ManyToOne".contentEquals(relationType)) && isOwnerSide && isAggregate && isOtherEntityAggregate; } public List findOwnedOneToManyRelationships(Map entity, Options options) { diff --git a/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendDefaultApplicationGenerator.java b/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendDefaultApplicationGenerator.java index 453f982f..fa01f403 100644 --- a/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendDefaultApplicationGenerator.java +++ b/plugins/backend-application-default/src/main/java/io/zenwave360/sdk/plugins/BackendDefaultApplicationGenerator.java @@ -82,6 +82,9 @@ public class BackendDefaultApplicationGenerator extends AbstractZDLProjectGenera @DocumentedOption(description = "Whether to add IEntityEventProducer interfaces as service dependencies. Depends on the naming convention of zenwave-asyncapi plugin to work.") public boolean includeEmitEventsImplementation = false; + @DocumentedOption(description = "Controls whether to add a read/write relationship by id when mapping relationships between aggregate (not recommended) keeping the relationship by object readonly.") + public boolean addRelationshipsById = false; + @DocumentedOption(description = "Specifies the Java data type for the ID fields of entities. Defaults to Long for JPA and String for MongoDB if not explicitly set.") public String idJavaType; diff --git a/plugins/backend-application-default/src/test/java/io/zenwave360/sdk/plugins/BackendApplicationJpaImperativeGeneratorTest.java b/plugins/backend-application-default/src/test/java/io/zenwave360/sdk/plugins/BackendApplicationJpaImperativeGeneratorTest.java index 0fdeefdc..2e9be3e3 100644 --- a/plugins/backend-application-default/src/test/java/io/zenwave360/sdk/plugins/BackendApplicationJpaImperativeGeneratorTest.java +++ b/plugins/backend-application-default/src/test/java/io/zenwave360/sdk/plugins/BackendApplicationJpaImperativeGeneratorTest.java @@ -53,4 +53,27 @@ public void test_generator_hexagonal_jpa() throws Exception { Assertions.assertEquals(0, exitCode); } + @Test + public void test_generator_maps_id() throws Exception { + String targetFolder = "target/zdl/test_generator_maps_id"; + Plugin plugin = new BackendApplicationDefaultPlugin() + .withZdlFile("classpath:io/zenwave360/sdk/resources/zdl/customer-address-one-to-one-maps-id.zdl") + .withTargetFolder(targetFolder) + .withOption("basePackage", "io.zenwave360.example") + .withOption("persistence", PersistenceType.jpa) + .withOption("style", ProgrammingStyle.imperative) + .withOption("projectName", "customer-address") + .withOption("forceOverwrite", true) + .withOption("haltOnFailFormatting", false); + + new MainGenerator().generate(plugin); + + List logs = logCaptor.getLogs(); + // Assertions.assertTrue(logs.contains("Writing template with targetFile: io/example/integration/test/api/provider_for_commands_reactive/DoCreateProductConsumer.java")); + // Assertions.assertTrue(logs.contains("Writing template with targetFile: io/example/integration/test/api/provider_for_commands_reactive/DoCreateProductService.java")); + + int exitCode = MavenCompiler.copyPomAndCompile("src/test/resources/jpa-elasticsearch-scs3-pom.xml", targetFolder); + Assertions.assertEquals(0, exitCode); + } + } diff --git a/zenwave-sdk-cli/src/main/java/io/zenwave360/sdk/processors/ZDLProcessor.java b/zenwave-sdk-cli/src/main/java/io/zenwave360/sdk/processors/ZDLProcessor.java index 1d3e6166..25bc5a16 100644 --- a/zenwave-sdk-cli/src/main/java/io/zenwave360/sdk/processors/ZDLProcessor.java +++ b/zenwave-sdk-cli/src/main/java/io/zenwave360/sdk/processors/ZDLProcessor.java @@ -138,13 +138,14 @@ protected Map buildRelationship(String entityName, Map relationship) { Map relationshipMap = Maps.of("type", relationship.get("type"), "_relationship", relationship); var from = relationship.get("from"); var to = relationship.get("to"); + var isMapsId = JSONPath.get(relationship, "toOptions.Id", false); if (from.equals(entityName)) { relationshipMap.put("entityName", from); relationshipMap.put("otherEntityName", to); relationshipMap.put("ownerSide", true); relationshipMap.put("options", relationship.get("fromOptions")); relationshipMap.put("validations", relationship.get("fromValidations")); -// relationshipMap.put("mapsId", JSONPath.get(relationship, "toOptions.Id", false)); + relationshipMap.put("isMapsIdParent", isMapsId); relationshipMap.put("isCollection", relationship.get("type").toString().endsWith("Many")); if(relationship.get("injectedFieldInFrom") != null) { var fillInjectedFieldInFrom = StringUtils.replace((String) relationship.get("injectedFieldInFrom"), ")","").split("\\("); @@ -161,7 +162,7 @@ protected Map buildRelationship(String entityName, Map relationship) { relationshipMap.put("ownerSide", false); relationshipMap.put("options", relationship.get("toOptions")); relationshipMap.put("validations", relationship.get("toValidations")); - relationshipMap.put("mapsId", JSONPath.get(relationship, "toOptions.Id", false)); + relationshipMap.put("mapsId", isMapsId); relationshipMap.put("isCollection", relationship.get("type").toString().startsWith("Many")); if(relationship.get("injectedFieldInTo") != null) { var fillInjectedFieldInFrom = StringUtils.replace((String) relationship.get("injectedFieldInTo"), ")","").split("\\("); diff --git a/zenwave-sdk-test-resources/src/main/resources/io/zenwave360/sdk/resources/zdl/customer-address-one-to-one-maps-id.zdl b/zenwave-sdk-test-resources/src/main/resources/io/zenwave360/sdk/resources/zdl/customer-address-one-to-one-maps-id.zdl new file mode 100644 index 00000000..c3aeeb06 --- /dev/null +++ b/zenwave-sdk-test-resources/src/main/resources/io/zenwave360/sdk/resources/zdl/customer-address-one-to-one-maps-id.zdl @@ -0,0 +1,31 @@ +/** +* Global javadoc comment +*/ + +MAX_LENGTH=100 + +/** +* Customer javadoc comment +*/ +@aggregate +entity Customer { + username String required unique minlength(3) /** username javadoc comment */ + email String required unique /** email javadoc comment */ +} + +enum AddressType { HOME(1) /** home description */, WORK(1) /** work description */ } + +@aggregate +entity Address { + street String /** street javadoc comment */ + city String /** city javadoc comment */ + state String /** state javadoc comment */ + zip String /** zip javadoc comment */ + type AddressType /** address type is an enum */ +} + +relationship OneToOne { + Customer{address} to @Id Address{customer} +} + +service Customer,Address with CustomerService