diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java index 91e240ee1..973761f7c 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java @@ -24,7 +24,7 @@ import java.util.Set; import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Type; -import org.mapstruct.ap.internal.model.source.Method; +import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.source.PropertyEntry; import org.mapstruct.ap.internal.util.Strings; import org.mapstruct.ap.internal.util.ValueProvider; @@ -44,10 +44,11 @@ public class NestedPropertyMappingMethod extends MappingMethod { public static class Builder { - private Method method; + private MappingBuilderContext ctx; + private ForgedMethod method; private List propertyEntries; - public Builder method( Method sourceMethod ) { + public Builder method( ForgedMethod sourceMethod ) { this.method = sourceMethod; return this; } @@ -57,22 +58,31 @@ public class NestedPropertyMappingMethod extends MappingMethod { return this; } + public Builder mappingContext(MappingBuilderContext mappingContext) { + this.ctx = mappingContext; + return this; + } + public NestedPropertyMappingMethod build() { List existingVariableNames = new ArrayList(); for ( Parameter parameter : method.getSourceParameters() ) { existingVariableNames.add( parameter.getName() ); } + final List thrownTypes = new ArrayList(); List safePropertyEntries = new ArrayList(); for ( PropertyEntry propertyEntry : propertyEntries ) { String safeName = Strings.getSaveVariableName( propertyEntry.getName(), existingVariableNames ); safePropertyEntries.add( new SafePropertyEntry( propertyEntry, safeName ) ); existingVariableNames.add( safeName ); + thrownTypes.addAll( ctx.getTypeFactory().getThrownTypes( + propertyEntry.getReadAccessor() ) ); } + method.addThrownTypes( thrownTypes ); return new NestedPropertyMappingMethod( method, safePropertyEntries ); } } - private NestedPropertyMappingMethod( Method method, List sourcePropertyEntries ) { + private NestedPropertyMappingMethod( ForgedMethod method, List sourcePropertyEntries ) { super( method ); this.safePropertyEntries = sourcePropertyEntries; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java index b893cf312..a455f6d78 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java @@ -504,6 +504,7 @@ public class PropertyMapping extends ModelElement { NestedPropertyMappingMethod nestedPropertyMapping = builder .method( methodRef ) .propertyEntries( sourceReference.getPropertyEntries() ) + .mappingContext( ctx ) .build(); // add if not yet existing diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java index 89c3a2d90..062d67fa6 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/TypeFactory.java @@ -382,7 +382,24 @@ public class TypeFactory { public List getThrownTypes(ExecutableType method) { List thrownTypes = new ArrayList(); for ( TypeMirror exceptionType : method.getThrownTypes() ) { - thrownTypes.add( getType( exceptionType ) ); + Type t = getType( exceptionType ); + if (!thrownTypes.contains( t )) { + thrownTypes.add( t ); + } + } + return thrownTypes; + } + + public List getThrownTypes(Accessor accessor) { + if (accessor.getExecutable() == null) { + return new ArrayList(); + } + List thrownTypes = new ArrayList(); + for (TypeMirror thrownType : accessor.getExecutable().getThrownTypes()) { + Type t = getType( thrownType ); + if (!thrownTypes.contains( t )) { + thrownTypes.add( t ); + } } return thrownTypes; } diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl index 51f6fae68..337c6d556 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.ftl @@ -19,7 +19,7 @@ limitations under the License. --> -<#lt>private <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, ) { +<#lt>private <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, )<@throws/> { if ( ${sourceParameter.name} == null ) { return ${returnType.null}; } @@ -43,3 +43,11 @@ } <#macro localVarName index><#if index == 0>${sourceParameter.name}<#else>${propertyEntries[index-1].name} +<#macro throws> + <#if (thrownTypes?size > 0)><#lt> throws <@compress single_line=true> + <#list thrownTypes as exceptionType> + <@includeModel object=exceptionType/> + <#if exceptionType_has_next>, <#t> + + + \ No newline at end of file diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/Bucket.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/Bucket.java new file mode 100644 index 000000000..d541723c2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/Bucket.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +/** + * + * @author Richard Lea + */ +public class Bucket { + + String userId; + + public Bucket(String userId) { + this.userId = userId; + } + + public User getUser() throws NoSuchUser { + throw new NoSuchUser(); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/NestedExceptionTest.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/NestedExceptionTest.java new file mode 100644 index 000000000..06b481eac --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/NestedExceptionTest.java @@ -0,0 +1,47 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * + * @author Richard Lea + */ +@WithClasses({ + Bucket.class, + User.class, + Resource.class, + ResourceDto.class, + NoSuchUser.class, + ResourceMapper.class +}) +@IssueKey("1332") +@RunWith(AnnotationProcessorTestRunner.class) +public class NestedExceptionTest { + + @Test + public void shouldGenerateCodeThatCompiles() { + + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/NoSuchUser.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/NoSuchUser.java new file mode 100644 index 000000000..a7e21a480 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/NoSuchUser.java @@ -0,0 +1,30 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +/** + * + * @author Richard Lea + */ +public class NoSuchUser extends Exception { + + public NoSuchUser() { + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/Resource.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/Resource.java new file mode 100644 index 000000000..255e05e10 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/Resource.java @@ -0,0 +1,32 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +/** + * + * @author Richard Lea + */ +public class Resource { + + private final Bucket bucket = new Bucket("2345"); + + public Bucket getBucket() { + return bucket; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/ResourceDto.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/ResourceDto.java new file mode 100644 index 000000000..00c720aa7 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/ResourceDto.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +/** + * + * @author Richard Lea + */ +public class ResourceDto { + + private String userId; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/ResourceMapper.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/ResourceMapper.java new file mode 100644 index 000000000..86c43b48f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/ResourceMapper.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +/** + * + * @author Richard Lea + */ +@Mapper() +public interface ResourceMapper { + + @Mappings({ + @Mapping(source = "bucket.user.uuid", target = "userId") + }) + ResourceDto map(Resource r) throws NoSuchUser; + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/User.java b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/User.java new file mode 100644 index 000000000..b7c81e33f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/nestedsource/exceptions/User.java @@ -0,0 +1,44 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.nestedsource.exceptions; + +/** + * + * @author Richard Lea + */ +public class User { + + private final String uuid; + + private final String name; + + public User(String uuid, String name) { + this.uuid = uuid; + this.name = name; + } + + public String getName() { + return name; + } + + public String getUuid() { + return uuid; + } + +}