Skip to content

Commit 53028be

Browse files
Extend POJO generator with options for setters
1 parent 3fa21ea commit 53028be

File tree

7 files changed

+157
-23
lines changed

7 files changed

+157
-23
lines changed

core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/AspectModelJavaUtil.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
import java.util.stream.Collectors;
3030
import java.util.stream.IntStream;
3131
import java.util.stream.Stream;
32+
3233
import javax.xml.datatype.DatatypeConstants;
34+
3335
import org.eclipse.esmf.aspectmodel.VersionInfo;
3436
import org.eclipse.esmf.aspectmodel.java.exception.CodeGenerationException;
3537
import org.eclipse.esmf.aspectmodel.visitor.AspectStreamTraversalVisitor;
@@ -121,7 +123,7 @@ public static String getPropertyType( final Property property, final JavaCodeGen
121123
*/
122124
public static boolean hasContainerType( final Property property ) {
123125
return property.isOptional()
124-
|| ( property.getEffectiveCharacteristic().map( characteristic -> characteristic.is( Collection.class ) ).orElse( false ) );
126+
|| (property.getEffectiveCharacteristic().map( characteristic -> characteristic.is( Collection.class ) ).orElse( false ));
125127
}
126128

127129
/**
@@ -324,8 +326,8 @@ public static String getDataType( final Optional<Type> dataType, final ImportTra
324326
return dataType.map( type -> {
325327
final Type actualDataType = dataType.get();
326328
if ( actualDataType instanceof ComplexType ) {
327-
final String complexDataType = ( (ComplexType) actualDataType ).getName();
328-
if ( ( !codeGenerationConfig.namePrefix().isBlank() || !codeGenerationConfig.namePostfix().isBlank() ) ) {
329+
final String complexDataType = ((ComplexType) actualDataType).getName();
330+
if ( (!codeGenerationConfig.namePrefix().isBlank() || !codeGenerationConfig.namePostfix().isBlank()) ) {
329331
return codeGenerationConfig.namePrefix() + complexDataType + codeGenerationConfig.namePostfix();
330332
}
331333
return complexDataType;
@@ -349,7 +351,7 @@ public static String getDataType( final Optional<Type> dataType, final ImportTra
349351

350352
public static Class<?> getDataTypeClass( final Type dataType ) {
351353
if ( dataType instanceof ComplexType ) {
352-
return ( (ComplexType) dataType ).getClass();
354+
return ((ComplexType) dataType).getClass();
353355
}
354356

355357
final Resource typeResource = ResourceFactory.createResource( dataType.getUrn() );
@@ -575,7 +577,7 @@ public static String genericClassSignature( final StructureElement element ) {
575577
}
576578

577579
public static String generateClassName( final StructureElement element, final JavaCodeGenerationConfig config ) {
578-
if ( ( !config.namePrefix().isBlank() || !config.namePostfix().isBlank() ) && element.is( StructureElement.class ) ) {
580+
if ( (!config.namePrefix().isBlank() || !config.namePostfix().isBlank()) && element.is( StructureElement.class ) ) {
579581
return config.namePrefix() + element.getName() + config.namePostfix();
580582
}
581583
return element.getName();
@@ -674,6 +676,15 @@ public static String getterName( final Property property ) {
674676
return (isBooleanType ? "is" : "get") + StringUtils.capitalize( property.getPayloadName() );
675677
}
676678

679+
public static String setterName( final Property property, final JavaCodeGenerationConfig codeGenerationConfig ) {
680+
switch ( codeGenerationConfig.setterStyle() ) {
681+
case FLUENT_COMPACT:
682+
return StringUtils.uncapitalize( property.getPayloadName() );
683+
default:
684+
return "set" + StringUtils.capitalize( property.getPayloadName() );
685+
}
686+
}
687+
677688
public static String codeGeneratorName() {
678689
return "esmf-sdk " + VersionInfo.ESMF_SDK_VERSION;
679690
}

core/esmf-aspect-model-java-generator/src/main/java/org/eclipse/esmf/aspectmodel/java/JavaCodeGenerationConfig.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
* @param jsonTypeInfo Corresponds to com.fasterxml.jackson.annotation.JsonTypeInfo.Id and selects which JsonTypeInfo kind is used
2828
* @param packageName the package name that classes should be created in
2929
* @param importTracker the instance of the tracker that tracks imports during code generation
30-
* @param executeLibraryMacros determines whether template macros given in templateLibFile should be evaluatated
30+
* @param executeLibraryMacros determines whether template macros given in templateLibFile should be evaluated
3131
* @param templateLibFile a file containing velocity macros overriding sections in the default code templates
3232
* @param namePrefix custom class name prefix
3333
* @param namePostfix custom class name postfix
34+
* @param enableSetters controls whether setters should be generated for the properties of the generated Java classes
35+
* @param setterStyle the style of setters to be generated, if {@code enableSetters} is true
3436
*/
3537
@RecordBuilder
3638
public record JavaCodeGenerationConfig(
@@ -42,12 +44,18 @@ public record JavaCodeGenerationConfig(
4244
boolean executeLibraryMacros,
4345
File templateLibFile,
4446
String namePrefix,
45-
String namePostfix
47+
String namePostfix,
48+
boolean enableSetters,
49+
SetterStyle setterStyle
4650
) implements GenerationConfig {
4751
public enum JsonTypeInfoType {
4852
NONE, CLASS, MINIMAL_CLASS, NAME, SIMPLE_NAME, DEDUCTION, CUSTOM
4953
}
5054

55+
public enum SetterStyle {
56+
STANDARD, FLUENT, FLUENT_COMPACT
57+
}
58+
5159
public JavaCodeGenerationConfig {
5260
if ( enableJacksonAnnotationJsonFormatShapeObject == null ) {
5361
enableJacksonAnnotationJsonFormatShapeObject = true;
@@ -61,7 +69,7 @@ public enum JsonTypeInfoType {
6169
if ( importTracker == null ) {
6270
importTracker = new ImportTracker();
6371
}
64-
if ( executeLibraryMacros && ( templateLibFile == null || templateLibFile.toString().isEmpty() ) ) {
72+
if ( executeLibraryMacros && (templateLibFile == null || templateLibFile.toString().isEmpty()) ) {
6573
throw new CodeGenerationException( "Missing configuration. Please provide path to velocity template library file." );
6674
}
6775
if ( executeLibraryMacros && !templateLibFile.exists() ) {
@@ -73,5 +81,8 @@ public enum JsonTypeInfoType {
7381
if ( namePostfix == null ) {
7482
namePostfix = "";
7583
}
84+
if (setterStyle == null ) {
85+
setterStyle = SetterStyle.STANDARD;
86+
}
7687
}
7788
}

core/esmf-aspect-model-java-generator/src/main/resources/java-pojo-class-body-lib.vm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
#parse( "java-pojo-property-lib.vm" )
1414
#parse( "java-pojo-constructor-lib.vm" )
1515
#parse( "java-pojo-getter-lib.vm" )
16+
#parse( "java-pojo-setter-lib.vm" )
1617
#parse( "java-pojo-equals-method-lib.vm" )
1718
#parse( "java-pojo-hashcode-method-lib.vm" )
1819

1920
#macro( javaPojoClassBody )
21+
#set( $className = ${util.generateClassName( $element, $codeGenerationConfig )}+${util.genericClassSignature( $element )} )
2022
/**
2123
* Generated class for $element.getPreferredName( $localeEn ) (${elementUrn}).
2224
*#if ( $element.getDescription( $localeEn ) ) $element.getDescription( $localeEn )#end
@@ -29,7 +31,7 @@ ${util.determineCollectionAspectClassDefinition( $element, $codeGenerationConfig
2931
${util.generateAbstractEntityClassAnnotations( $complexElement, $codeGenerationConfig, $extendingEntities )}
3032
${util.determineComplexTypeClassDefinition( $complexElement, $codeGenerationConfig )}
3133
#else
32-
public class ${util.generateClassName( $element, $codeGenerationConfig )}${util.genericClassSignature( $element )} {
34+
public class ${className} {
3335
#end
3436
#foreach( $property in $element.properties )
3537
#javaPojoProperty( $property )
@@ -43,6 +45,9 @@ public class ${util.generateClassName( $element, $codeGenerationConfig )}${util.
4345
#foreach( $property in $element.properties )
4446
#set( $index = $foreach.count - 1 )
4547
#javaPojoGetter( $property, $index )
48+
#if ( $codeGenerationConfig.enableSetters() )
49+
#javaPojoSetter( $property, $index, $className )
50+
#end
4651
#end
4752
#foreach( $property in $deconstructor.allProperties )
4853
#javaPojoGetter( $property, 0 )
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#**
2+
~ Copyright (c) 2021 Robert Bosch Manufacturing Solutions GmbH
3+
~
4+
~ See the AUTHORS file(s) distributed with this work for additional
5+
~ information regarding authorship.
6+
~
7+
~ This Source Code Form is subject to the terms of the Mozilla Public
8+
~ License, v. 2.0. If a copy of the MPL was not distributed with this
9+
~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
~
11+
~ SPDX-License-Identifier: MPL-2.0
12+
*#
13+
14+
#macro( javaPojoSetter $property $propertyIndex $className )
15+
16+
#set( $methodName = $util.setterName( $property, $codeGenerationConfig ) )
17+
#if ( $codeGenerationConfig.setterStyle().name().equals( "STANDARD" ) )
18+
#set( $returnType = "void" )
19+
#else
20+
#set( $returnType = $className )
21+
#end
22+
/**
23+
* Sets a new value for $property.getPreferredName( $localeEn )
24+
#if( !$codeGenerationConfig.setterStyle().name().equals( "STANDARD" ) )
25+
*
26+
* @return {@code this} for chaining
27+
#end
28+
*/
29+
#if( $property.isAbstract() )
30+
public abstract ${returnType} $methodName( $propertyType $property.getPayloadName() );
31+
#else
32+
#set( $propertyType = $util.getPropertyType( $property, false, $codeGenerationConfig ) )
33+
#if( $property.getExtends().isPresent() )@Override #end
34+
public $returnType $methodName( final $propertyType $property.getPayloadName() ) {
35+
this.$property.getPayloadName() = $property.getPayloadName();
36+
#if( !$codeGenerationConfig.setterStyle().name().equals( "STANDARD" ) )
37+
return this;
38+
#end
39+
}
40+
#end
41+
#end

core/esmf-aspect-model-java-generator/src/test/java/org/eclipse/esmf/aspectmodel/java/AspectModelJavaGeneratorTest.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.github.javaparser.ast.NodeList;
4848
import com.github.javaparser.ast.body.ConstructorDeclaration;
4949
import com.github.javaparser.ast.body.Parameter;
50+
import com.github.javaparser.ast.type.ClassOrInterfaceType;
5051
import com.github.javaparser.ast.type.PrimitiveType;
5152
import com.github.javaparser.resolution.types.ResolvedArrayType;
5253
import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
@@ -104,14 +105,18 @@ private Collection<JavaGenerator> getGenerators( final AspectModel aspectModel )
104105
return List.of( new AspectModelJavaGenerator( aspectModel.aspect(), config ) );
105106
}
106107

107-
private Collection<JavaGenerator> getGenerators( final TestAspect testAspect, final String namePrefix, final String namePostfix ) {
108+
private Collection<JavaGenerator> getGenerators( final TestAspect testAspect, final String namePrefix, final String namePostfix,
109+
final boolean enableSetters, final
110+
JavaCodeGenerationConfig.SetterStyle setterStyle ) {
108111
final AspectModel aspectModel = TestResources.load( testAspect );
109112
final JavaCodeGenerationConfig config = JavaCodeGenerationConfigBuilder.builder()
110113
.enableJacksonAnnotations( true )
111114
.executeLibraryMacros( false )
112115
.packageName( aspectModel.aspect().urn().getNamespaceMainPart() )
113116
.namePrefix( namePrefix )
114117
.namePostfix( namePostfix )
118+
.enableSetters( enableSetters )
119+
.setterStyle( setterStyle )
115120
.build();
116121
return List.of( new AspectModelJavaGenerator( aspectModel.aspect(), config ) );
117122
}
@@ -624,9 +629,9 @@ void testGenerateAspectModelMultipleEntitiesOnMultipleLevelsWithoutJacksonAnnota
624629
void testGenerateAspectWithStructuredValue() throws IOException {
625630
final ImmutableMap<String, Object> expectedFieldsForAspectClass = ImmutableMap.<String, Object> builder()
626631
.put( "date", XMLGregorianCalendar.class )
627-
.put( "year", new TypeToken<Optional<Long>>(){}.getType() )
628-
.put( "month", new TypeToken<Optional<Long>>(){}.getType() )
629-
.put( "day", new TypeToken<Optional<Long>>(){}.getType() )
632+
.put( "year", new TypeToken<Optional<Long>>() {}.getType() )
633+
.put( "month", new TypeToken<Optional<Long>>() {}.getType() )
634+
.put( "day", new TypeToken<Optional<Long>>() {}.getType() )
630635
.build();
631636

632637
final ImmutableMap<String, Object> expectedConstructorArguments = ImmutableMap.<String, Object> builder()
@@ -1183,7 +1188,7 @@ void testGenerateAspectWithPrefixAndPostfix() throws IOException {
11831188

11841189
final TestAspect aspect = TestAspect.ASPECT_WITH_PROPERTY;
11851190
final GenerationResult result = TestContext.generateAspectCode()
1186-
.apply( getGenerators( aspect, "Base", "Postfix" ) );
1191+
.apply( getGenerators( aspect, "Base", "Postfix", false, null ) );
11871192
result.assertNumberOfFiles( 1 );
11881193
result.assertFields( "BaseAspectWithPropertyPostfix", expectedFieldsForAspectClass, new HashMap<>() );
11891194
assertConstructor( result, "BaseAspectWithPropertyPostfix", expectedFieldsForAspectClass );
@@ -1197,9 +1202,50 @@ void testGenerateEntityWithPrefixAndPostfix() throws IOException {
11971202

11981203
final TestAspect aspect = TestAspect.ASPECT_WITH_ENTITY;
11991204
final GenerationResult result = TestContext.generateAspectCode()
1200-
.apply( getGenerators( aspect, "Base", "Postfix" ) );
1205+
.apply( getGenerators( aspect, "Base", "Postfix", false, null ) );
12011206
result.assertNumberOfFiles( 2 );
12021207
result.assertFields( "BaseAspectWithEntityPostfix", expectedFieldsForAspectClass, new HashMap<>() );
12031208
assertConstructor( result, "BaseAspectWithEntityPostfix", expectedFieldsForAspectClass );
12041209
}
1210+
1211+
@Test
1212+
void testGenerateAspectWithStandardSetters() throws IOException {
1213+
final TestAspect aspect = TestAspect.ASPECT_WITH_ENTITY;
1214+
final GenerationResult result = TestContext.generateAspectCode()
1215+
.apply( getGenerators( aspect, null, null, true, JavaCodeGenerationConfig.SetterStyle.STANDARD ) );
1216+
result.assertNumberOfFiles( 2 );
1217+
1218+
result.assertMethodBody( "AspectWithEntity", "setTestProperty", false, Optional.empty(), 1,
1219+
List.of( "this.testProperty=testProperty;" ) );
1220+
result.assertMethodBody( "TestEntity", "setEntityProperty", false, Optional.empty(), 1,
1221+
List.of( "this.entityProperty=entityProperty;" ) );
1222+
}
1223+
1224+
@Test
1225+
void testGenerateAspectWithFluentSetters() throws IOException {
1226+
final TestAspect aspect = TestAspect.ASPECT_WITH_ENTITY;
1227+
final GenerationResult result = TestContext.generateAspectCode()
1228+
.apply( getGenerators( aspect, null, null, true, JavaCodeGenerationConfig.SetterStyle.FLUENT ) );
1229+
result.assertNumberOfFiles( 2 );
1230+
1231+
result.assertMethodBody( "AspectWithEntity", "setTestProperty", false, Optional.of( new ClassOrInterfaceType( "AspectWithEntity" ) ),
1232+
1,
1233+
List.of( "this.testProperty=testProperty;", "returnthis;" ) );
1234+
result.assertMethodBody( "TestEntity", "setEntityProperty", false, Optional.of( new ClassOrInterfaceType( "TestEntity" ) ), 1,
1235+
List.of( "this.entityProperty=entityProperty;", "returnthis;" ) );
1236+
}
1237+
1238+
@Test
1239+
void testGenerateAspectWithCompactFluentSetters() throws IOException {
1240+
final TestAspect aspect = TestAspect.ASPECT_WITH_ENTITY;
1241+
final GenerationResult result = TestContext.generateAspectCode()
1242+
.apply( getGenerators( aspect, null, null, true, JavaCodeGenerationConfig.SetterStyle.FLUENT_COMPACT ) );
1243+
result.assertNumberOfFiles( 2 );
1244+
1245+
result.assertMethodBody( "AspectWithEntity", "testProperty", false, Optional.of( new ClassOrInterfaceType( "AspectWithEntity" ) ),
1246+
1,
1247+
List.of( "this.testProperty=testProperty;", "returnthis;" ) );
1248+
result.assertMethodBody( "TestEntity", "entityProperty", false, Optional.of( new ClassOrInterfaceType( "TestEntity" ) ), 1,
1249+
List.of( "this.entityProperty=entityProperty;", "returnthis;" ) );
1250+
}
12051251
}

core/esmf-aspect-model-java-generator/src/test/java/org/eclipse/esmf/aspectmodel/java/GenerationResult.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Set;
2727
import java.util.function.Function;
2828
import java.util.stream.Collectors;
29+
2930
import javax.annotation.processing.Generated;
3031

3132
import com.github.javaparser.ParseResult;
@@ -46,7 +47,6 @@
4647
import com.github.javaparser.ast.expr.SimpleName;
4748
import com.github.javaparser.ast.stmt.Statement;
4849
import com.github.javaparser.ast.type.ClassOrInterfaceType;
49-
import com.github.javaparser.ast.type.PrimitiveType;
5050
import com.github.javaparser.resolution.types.ResolvedReferenceType;
5151
import com.github.javaparser.resolution.types.ResolvedType;
5252
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
@@ -190,7 +190,7 @@ void assertConstructorBody( final String className, final Set<String> expectedbo
190190
}
191191

192192
void assertMethodBody( final String className, final String methodName, final boolean override,
193-
final Optional<PrimitiveType> expectedReturnType,
193+
final Optional<? extends com.github.javaparser.ast.type.Type> expectedReturnType,
194194
final int expectedNumberOfParameters, final List<String> expectedMethodBody ) {
195195
final Optional<MethodDeclaration> possibleMethodDeclaration = compilationUnits.get( className )
196196
.findAll( MethodDeclaration.class ).stream()
@@ -219,7 +219,7 @@ void assertMethodBody( final String className, final String methodName, final bo
219219
private TypeToken typeTokenToCheck( final Object fieldTypeOrTypeName ) {
220220
TypeToken typeToCheck;
221221
if ( fieldTypeOrTypeName instanceof TypeToken ) {
222-
typeToCheck = ( (TypeToken) fieldTypeOrTypeName );
222+
typeToCheck = ((TypeToken) fieldTypeOrTypeName);
223223
} else {
224224
typeToCheck = TypeToken.of( (Type) fieldTypeOrTypeName );
225225
}
@@ -240,11 +240,11 @@ private TypeResolution resolveRecursive( final TypeResolution toResolve ) {
240240
entry.getKey().toString().equals( toResolve.getClassNameToResolve() ) )
241241
.findAny().map( Map.Entry::getValue ).orElseThrow( () -> new RuntimeException( e ) );
242242
}
243-
if ( !toResolve.getToResolve().isReferenceType() || ( (ResolvedReferenceType) toResolve.getToResolve() )
243+
if ( !toResolve.getToResolve().isReferenceType() || ((ResolvedReferenceType) toResolve.getToResolve())
244244
.getTypeParametersMap().isEmpty() ) {
245245
return TypeResolution.resolved( rawType );
246246
}
247-
final Type[] typeParameters = ( (ResolvedReferenceType) toResolve.getToResolve() )
247+
final Type[] typeParameters = ((ResolvedReferenceType) toResolve.getToResolve())
248248
.getTypeParametersMap()
249249
.stream()
250250
.map( pair -> pair.b )

0 commit comments

Comments
 (0)