diff --git a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
index ab43cc4cba..f3faf85e20 100644
--- a/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
+++ b/integrationtest/src/test/java/org/mapstruct/itest/tests/MavenIntegrationTest.java
@@ -222,4 +222,12 @@ void usesTypeGenerationTestEclipse() {
void faultyAstModifyingProcessor() {
}
+ /**
+ * For sealed interface, create an impl class with the switch case.
+ */
+ @ProcessorTest(baseDir = "sealedInterfaceTest")
+ @EnabledForJreRange(min = JRE.JAVA_21)
+ void sealedInterfaceSubclassMappingTest() {
+ }
+
}
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/pom.xml b/integrationtest/src/test/resources/sealedInterfaceTest/pom.xml
new file mode 100644
index 0000000000..655c188b3d
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/pom.xml
@@ -0,0 +1,103 @@
+
+
+
+ 4.0.0
+
+
+ org.mapstruct
+ mapstruct-it-parent
+ 1.0.0
+ ../pom.xml
+
+
+ sealedInterfaceTest
+ jar
+
+
+
+ generate-via-compiler-plugin
+
+ false
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ \${compiler-id}
+ --enable-preview
+
+
+
+ org.eclipse.tycho
+ tycho-compiler-jdt
+ ${org.eclipse.tycho.compiler-jdt.version}
+
+
+
+
+
+
+
+ ${project.groupId}
+ mapstruct-processor
+ ${mapstruct.version}
+ provided
+
+
+
+
+ debug-forked-javac
+
+ false
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+
+ true
+
+ --enable-preview
+ -J-Xdebug
+ -J-Xnoagent
+ -J-Djava.compiler=NONE
+ -J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ 1
+ --enable-preview
+
+
+
+
+
+
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/From.java b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/From.java
new file mode 100644
index 0000000000..4e8f39984a
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/From.java
@@ -0,0 +1,8 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.sealedinterface;
+
+public sealed interface From permits FromA, FromB {}
\ No newline at end of file
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/FromA.java b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/FromA.java
new file mode 100644
index 0000000000..d0f92d816f
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/FromA.java
@@ -0,0 +1,8 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.sealedinterface;
+
+public record FromA(int a) implements From {}
\ No newline at end of file
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/FromB.java b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/FromB.java
new file mode 100644
index 0000000000..2c1ab4b299
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/FromB.java
@@ -0,0 +1,8 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.sealedinterface;
+
+public record FromB(int b) implements From {}
\ No newline at end of file
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/Issue3836Mapper.java b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/Issue3836Mapper.java
new file mode 100644
index 0000000000..4e9d983488
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/Issue3836Mapper.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.sealedinterface;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.ReportingPolicy;
+import org.mapstruct.SubclassMapping;
+import org.mapstruct.factory.Mappers;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN)
+public interface Issue3836Mapper {
+
+ Issue3836Mapper INSTANCE = Mappers.getMapper( Issue3836Mapper.class );
+
+ @Mapping(source = "a", target = "to")
+ To map(FromA from);
+
+ @Mapping(source = "b", target = "to")
+ To map(FromB fromB);
+
+ @SubclassMapping(source = FromA.class, target = To.class)
+ @SubclassMapping(source = FromB.class, target = To.class)
+ To map(From from);
+}
\ No newline at end of file
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/To.java b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/To.java
new file mode 100644
index 0000000000..c61cae9d59
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/src/main/java/org/mapstruct/itest/sealedinterface/To.java
@@ -0,0 +1,8 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.sealedinterface;
+
+public record To(int to) {}
\ No newline at end of file
diff --git a/integrationtest/src/test/resources/sealedInterfaceTest/src/test/java/org/mapstruct/itest/sealedinterface/SealedInterfaceTest.java b/integrationtest/src/test/resources/sealedInterfaceTest/src/test/java/org/mapstruct/itest/sealedinterface/SealedInterfaceTest.java
new file mode 100644
index 0000000000..c3eb45b3cd
--- /dev/null
+++ b/integrationtest/src/test/resources/sealedInterfaceTest/src/test/java/org/mapstruct/itest/sealedinterface/SealedInterfaceTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.itest.sealedinterface;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SealedInterfaceTest {
+
+ private final Issue3836Mapper mapper = Issue3836Mapper.INSTANCE;
+
+ @Test
+ public void shouldGeneratePatternSwitchInPolymorphicMapMethod() throws IOException {
+ Path generatedFile = Path.of("target/generated-sources/annotations/org/mapstruct/itest/sealedinterface/Issue3836MapperImpl.java");
+ String content = Files.readString(generatedFile);
+ assertThat(content.contains("switch (from) {")).isTrue();
+ assertThat(content.contains("case FromA fromA ->")).isTrue();
+ assertThat(content.contains("return map( (FromA) from );")).isTrue();
+ assertThat(content.contains("case FromB fromB ->")).isTrue();
+ assertThat(content.contains("return map( (FromB) from );")).isTrue();
+ assertThat(content.contains("if (from instanceof")).isFalse();
+ }
+
+ @Test
+ public void shouldMapFromAToTo() {
+ FromA fromA = new FromA(100);
+
+ To result = mapper.map(fromA);
+
+ assertThat(result).isNotNull();
+ assertThat(result.to()).isEqualTo(100);
+ }
+
+ @Test
+ public void shouldMapFromBToTo() {
+ FromB fromB = new FromB(200);
+
+ To result = mapper.map(fromB);
+
+ assertThat(result).isNotNull();
+ assertThat(result.to()).isEqualTo(200);
+ }
+
+ @Test
+ public void shouldMapFromInterfaceWithFromAInstance() {
+ From from = new FromA(300);
+
+ To result = mapper.map(from);
+
+ assertThat(result).isNotNull();
+ assertThat(result.to()).isEqualTo(300);
+ }
+
+ @Test
+ public void shouldMapFromInterfaceWithFromBInstance() {
+ From from = new FromB(400);
+
+ To result = mapper.map(from);
+
+ assertThat(result).isNotNull();
+ assertThat(result.to()).isEqualTo(400);
+ }
+
+ @Test
+ public void shouldReturnNullWhenInputIsNull() {
+ assertThat(mapper.map((FromA) null)).isNull();
+ assertThat(mapper.map((FromB) null)).isNull();
+ assertThat(mapper.map((From) null)).isNull();
+ }
+}
\ No newline at end of file
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java
index b5208d302b..f5c0b5a3e9 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java
@@ -532,18 +532,20 @@ private SubclassMapping createSubclassMapping(SubclassMappingOptions subclassMap
targetType,
mappingReferences ) );
String sourceArgument = null;
+ Type sourceArgumentType = null;
for ( Parameter parameter : method.getSourceParameters() ) {
if ( ctx
.getTypeUtils()
.isAssignable( sourceType.getTypeMirror(), parameter.getType().getTypeMirror() ) ) {
sourceArgument = parameter.getName();
+ sourceArgumentType = parameter.getType();
if ( assignment != null ) {
assignment.setSourceLocalVarName(
"(" + sourceType.createReferenceName() + ") " + sourceArgument );
}
}
}
- return new SubclassMapping( sourceType, sourceArgument, targetType, assignment );
+ return new SubclassMapping( sourceType, sourceArgument, sourceArgumentType, targetType, assignment );
}
private boolean isAbstractReturnTypeAllowed() {
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/SubclassMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/SubclassMapping.java
index 3ce42f68e5..bfb3c6cfde 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/SubclassMapping.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/SubclassMapping.java
@@ -28,10 +28,13 @@ public class SubclassMapping extends ModelElement {
private final Type targetType;
private final Assignment assignment;
private final String sourceArgument;
+ private final Type sourceArgumentType;
- public SubclassMapping(Type sourceType, String sourceArgument, Type targetType, Assignment assignment) {
+ public SubclassMapping(Type sourceType, String sourceArgument, Type sourceArgumentType,
+ Type targetType, Assignment assignment) {
this.sourceType = sourceType;
this.sourceArgument = sourceArgument;
+ this.sourceArgumentType = sourceArgumentType;
this.targetType = targetType;
this.assignment = assignment;
}
@@ -40,6 +43,10 @@ public Type getSourceType() {
return sourceType;
}
+ public Type getSourceArgumentType() {
+ return sourceArgumentType;
+ }
+
@Override
public Set getImportTypes() {
return Collections.singleton( sourceType );
diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl
index da590bb506..60d8b59d75 100644
--- a/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl
+++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl
@@ -34,127 +34,140 @@
#if>
<#if hasSubclassMappings()>
- <#list subclassMappings as subclass>
- <#if subclass_index > 0>else#if> if (${subclass.sourceArgument} instanceof <@includeModel object=subclass.sourceType/>) {
+ <#if subclassMappings[0].sourceArgumentType.isSealed()>
+ <#assign switchVar = subclassMappings[0].sourceArgument>
+ switch (${switchVar}) {
+ <#list subclassMappings as subclass>
+ case <@includeModel object=subclass.sourceType/> ${subclass.sourceType.name?uncap_first} -> {
<@includeModel object=subclass.assignment existingInstanceMapping=existingInstanceMapping/>
+ }
+ #list>
}
- #list>
- else {
+ <#else>
+ <#list subclassMappings as subclass>
+ <#if subclass_index > 0>else#if> if (${subclass.sourceArgument} instanceof <@includeModel object=subclass.sourceType/>) {
+ <@includeModel object=subclass.assignment existingInstanceMapping=existingInstanceMapping/>
+ }
+ #list>
+ else {
+ #if>
#if>
- <#if isAbstractReturnType()>
- throw new <@includeModel object=subclassExhaustiveException />("Not all subclasses are supported for this mapping. Missing for " + ${subclassMappings[0].sourceArgument}.getClass());
- <#else>
- <#if !existingInstanceMapping>
- <#if hasConstructorMappings()>
- <#if (sourceParameters?size > 1)>
- <#list sourceParametersNeedingPresenceCheck as sourceParam>
- <#if (constructorPropertyMappingsByParameter(sourceParam)?size > 0)>
- <#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
- <@includeModel object=propertyMapping.targetType /> ${propertyMapping.targetWriteAccessorName} = ${propertyMapping.targetType.null};
- #list>
- if ( <@includeModel object=getPresenceCheckByParameter(sourceParam) /> ) {
- <#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
- <@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
- #list>
+ <#if (!hasSubclassMappings() || !subclassMappings[0].sourceArgumentType.sealed)>
+ <#if isAbstractReturnType()>
+ throw new <@includeModel object=subclassExhaustiveException />("Not all subclasses are supported for this mapping. Missing for " + ${subclassMappings[0].sourceArgument}.getClass());
+ <#else>
+ <#if !existingInstanceMapping>
+ <#if hasConstructorMappings()>
+ <#if (sourceParameters?size > 1)>
+ <#list sourceParametersNeedingPresenceCheck as sourceParam>
+ <#if (constructorPropertyMappingsByParameter(sourceParam)?size > 0)>
+ <#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
+ <@includeModel object=propertyMapping.targetType /> ${propertyMapping.targetWriteAccessorName} = ${propertyMapping.targetType.null};
+ #list>
+ if ( <@includeModel object=getPresenceCheckByParameter(sourceParam) /> ) {
+ <#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
+ <@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
+ #list>
+ }
+ #if>
+ #list>
+ <#list sourceParametersNotNeedingPresenceCheck as sourceParam>
+ <#if (constructorPropertyMappingsByParameter(sourceParam)?size > 0)>
+ <#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
+ <@includeModel object=propertyMapping.targetType /> ${propertyMapping.targetWriteAccessorName} = ${propertyMapping.targetType.null};
+ <@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
+ #list>
+ #if>
+ #list>
+ <#else>
+ <#list constructorPropertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
+ <@includeModel object=propertyMapping.targetType /> ${propertyMapping.targetWriteAccessorName} = ${propertyMapping.targetType.null};
+ #list>
+ <#if mapNullToDefault>if ( <@includeModel object=getPresenceCheckByParameter(sourceParameters[0]) /> ) {#if>
+ <#list constructorPropertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
+ <@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
+ #list>
+ <#if mapNullToDefault>
}
#if>
- #list>
- <#list sourceParametersNotNeedingPresenceCheck as sourceParam>
- <#if (constructorPropertyMappingsByParameter(sourceParam)?size > 0)>
- <#list constructorPropertyMappingsByParameter(sourceParam) as propertyMapping>
- <@includeModel object=propertyMapping.targetType /> ${propertyMapping.targetWriteAccessorName} = ${propertyMapping.targetType.null};
- <@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
- #list>
- #if>
- #list>
- <#else>
- <#list constructorPropertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
- <@includeModel object=propertyMapping.targetType /> ${propertyMapping.targetWriteAccessorName} = ${propertyMapping.targetType.null};
- #list>
- <#if mapNullToDefault>if ( <@includeModel object=getPresenceCheckByParameter(sourceParameters[0]) /> ) {#if>
- <#list constructorPropertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
- <@includeModel object=propertyMapping existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
- #list>
- <#if mapNullToDefault>
- }
#if>
- #if>
- <#list constructorConstantMappings as constantMapping>
+ <#list constructorConstantMappings as constantMapping>
- <@compress single_line=true>
- <@includeModel object=constantMapping.targetType /> <@includeModel object=constantMapping existingInstanceMapping=existingInstanceMapping/>
- @compress>
- #list>
+ <@compress single_line=true>
+ <@includeModel object=constantMapping.targetType /> <@includeModel object=constantMapping existingInstanceMapping=existingInstanceMapping/>
+ @compress>
+ #list>
- <@includeModel object=returnTypeToConstruct/> ${resultName} = <@includeModel object=factoryMethod targetType=returnTypeToConstruct/>;
- <#else >
- <@includeModel object=returnTypeToConstruct/> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod targetType=returnTypeToConstruct/><#else>new <@includeModel object=returnTypeToConstruct/>()#if>;
- #if>
+ <@includeModel object=returnTypeToConstruct/> ${resultName} = <@includeModel object=factoryMethod targetType=returnTypeToConstruct/>;
+ <#else >
+ <@includeModel object=returnTypeToConstruct/> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod targetType=returnTypeToConstruct/><#else>new <@includeModel object=returnTypeToConstruct/>()#if>;
+ #if>
- #if>
- <#list beforeMappingReferencesWithMappingTarget as callback>
- <@includeModel object=callback targetBeanName=resultName targetType=targetType/>
- <#if !callback_has_next>
+ #if>
+ <#list beforeMappingReferencesWithMappingTarget as callback>
+ <@includeModel object=callback targetBeanName=resultName targetType=targetType/>
+ <#if !callback_has_next>
- #if>
- #list>
- <#if (sourceParameters?size > 1)>
- <#list sourceParametersNeedingPresenceCheck as sourceParam>
- <#if (propertyMappingsByParameter(sourceParam)?size > 0)>
- if ( <@includeModel object=getPresenceCheckByParameter(sourceParam) /> ) {
+ #if>
+ #list>
+ <#if (sourceParameters?size > 1)>
+ <#list sourceParametersNeedingPresenceCheck as sourceParam>
+ <#if (propertyMappingsByParameter(sourceParam)?size > 0)>
+ if ( <@includeModel object=getPresenceCheckByParameter(sourceParam) /> ) {
+ <#list propertyMappingsByParameter(sourceParam) as propertyMapping>
+ <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
+ #list>
+ }
+ #if>
+ #list>
+ <#list sourceParametersNotNeedingPresenceCheck as sourceParam>
+ <#if (propertyMappingsByParameter(sourceParam)?size > 0)>
<#list propertyMappingsByParameter(sourceParam) as propertyMapping>
<@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
#list>
- }
- #if>
+ #if>
+ #list>
+ <#elseif !propertyMappingsByParameter(sourceParameters[0]).empty>
+ <#if mapNullToDefault>if ( <@includeModel object=getPresenceCheckByParameter(sourceParameters[0]) /> ) {#if>
+ <#list propertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
+ <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
+ #list>
+ <#if mapNullToDefault>}#if>
+ #if>
+ <#list constantMappings as constantMapping>
+ <@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
#list>
- <#list sourceParametersNotNeedingPresenceCheck as sourceParam>
- <#if (propertyMappingsByParameter(sourceParam)?size > 0)>
- <#list propertyMappingsByParameter(sourceParam) as propertyMapping>
- <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
- #list>
+ <#list afterMappingReferences as callback>
+ <#if callback_index = 0>
+
#if>
+ <@includeModel object=callback targetBeanName=resultName targetType=targetType/>
#list>
- <#elseif !propertyMappingsByParameter(sourceParameters[0]).empty>
- <#if mapNullToDefault>if ( <@includeModel object=getPresenceCheckByParameter(sourceParameters[0]) /> ) {#if>
- <#list propertyMappingsByParameter(sourceParameters[0]) as propertyMapping>
- <@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping defaultValueAssignment=propertyMapping.defaultValueAssignment/>
- #list>
- <#if mapNullToDefault>}#if>
- #if>
- <#list constantMappings as constantMapping>
- <@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
- #list>
- <#list afterMappingReferences as callback>
- <#if callback_index = 0>
-
- #if>
- <@includeModel object=callback targetBeanName=resultName targetType=targetType/>
- #list>
- <#if returnType.name != "void">
+ <#if returnType.name != "void">
- <#if finalizerMethod??>
- <#if (afterMappingReferencesWithFinalizedReturnType?size > 0)>
- <@includeModel object=returnType /> ${finalizedResultName} = ${resultName}.<@includeModel object=finalizerMethod />;
+ <#if finalizerMethod??>
+ <#if (afterMappingReferencesWithFinalizedReturnType?size > 0)>
+ <@includeModel object=returnType /> ${finalizedResultName} = ${resultName}.<@includeModel object=finalizerMethod />;
- <#list afterMappingReferencesWithFinalizedReturnType as callback>
- <#if callback_index = 0>
+ <#list afterMappingReferencesWithFinalizedReturnType as callback>
+ <#if callback_index = 0>
- #if>
- <@includeModel object=callback targetBeanName=finalizedResultName targetType=returnType/>
- #list>
+ #if>
+ <@includeModel object=callback targetBeanName=finalizedResultName targetType=returnType/>
+ #list>
- return ${finalizedResultName};
+ return ${finalizedResultName};
+ <#else>
+ return ${resultName}.<@includeModel object=finalizerMethod />;
+ #if>
<#else>
- return ${resultName}.<@includeModel object=finalizerMethod />;
+ return ${resultName};
+ #if>
+ #if>
#if>
- <#else>
- return ${resultName};
- #if>
- #if>
#if>
- <#if hasSubclassMappings()>
+ <#if hasSubclassMappings() && !subclassMappings[0].sourceArgumentType.isSealed()>
}
#if>
}