Skip to content

Commit

Permalink
[plugins/backend-application-default] adds addRelationshipsById to …
Browse files Browse the repository at this point in the history
…control whether to add a read/write relationship by id when mapping relationships between aggregate (not recommended) keeping the relationship by object readonly.
  • Loading branch information
ivangsa committed Nov 25, 2024
1 parent 8274a91 commit cbefd56
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 21 deletions.
37 changes: 19 additions & 18 deletions plugins/backend-application-default/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Map> findOwnedOneToManyRelationships(Map entity, Options options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> 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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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("\\(");
Expand All @@ -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("\\(");
Expand Down
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit cbefd56

Please sign in to comment.