#198 fixing comments @agudian and applying throws clause to all MappingMethods

This commit is contained in:
sjaakd 2014-04-21 12:11:08 +02:00
parent 0ed14cd691
commit 51e33cb343
20 changed files with 259 additions and 36 deletions

View File

@ -39,7 +39,6 @@ public class BeanMappingMethod extends MappingMethod {
private final List<PropertyMapping> propertyMappings; private final List<PropertyMapping> propertyMappings;
private final FactoryMethod factoryMethod; private final FactoryMethod factoryMethod;
private final List<Type> exceptionTypes;
public BeanMappingMethod(SourceMethod method, public BeanMappingMethod(SourceMethod method,
List<PropertyMapping> propertyMappings, List<PropertyMapping> propertyMappings,
@ -47,7 +46,6 @@ public class BeanMappingMethod extends MappingMethod {
super( method ); super( method );
this.propertyMappings = propertyMappings; this.propertyMappings = propertyMappings;
this.factoryMethod = factoryMethod; this.factoryMethod = factoryMethod;
this.exceptionTypes = method.getExceptionTypes();
} }
public List<PropertyMapping> getPropertyMappings() { public List<PropertyMapping> getPropertyMappings() {
@ -83,8 +81,4 @@ public class BeanMappingMethod extends MappingMethod {
public FactoryMethod getFactoryMethod() { public FactoryMethod getFactoryMethod() {
return this.factoryMethod; return this.factoryMethod;
} }
public List<Type> getExceptionTypes() {
return exceptionTypes;
}
} }

View File

@ -42,6 +42,7 @@ public abstract class MappingMethod extends ModelElement {
private final Type returnType; private final Type returnType;
private final Parameter targetParameter; private final Parameter targetParameter;
private final Accessibility accessibility; private final Accessibility accessibility;
private final List<Type> thrownTypes;
protected MappingMethod(Method method) { protected MappingMethod(Method method) {
this.name = method.getName(); this.name = method.getName();
@ -49,6 +50,7 @@ public abstract class MappingMethod extends ModelElement {
this.returnType = method.getReturnType(); this.returnType = method.getReturnType();
this.targetParameter = method.getTargetParameter(); this.targetParameter = method.getTargetParameter();
this.accessibility = method.getAccessibility(); this.accessibility = method.getAccessibility();
this.thrownTypes = method.getThrownTypes();
} }
public String getName() { public String getName() {
@ -102,7 +104,7 @@ public abstract class MappingMethod extends ModelElement {
types.add( getReturnType() ); types.add( getReturnType() );
types.addAll( getReturnType().getImportTypes() ); types.addAll( getReturnType().getImportTypes() );
types.addAll( thrownTypes );
return types; return types;
} }
@ -116,6 +118,10 @@ public abstract class MappingMethod extends ModelElement {
return parameterNames; return parameterNames;
} }
public List<Type> getThrownTypes() {
return thrownTypes;
}
@Override @Override
public String toString() { public String toString() {
return returnType + " " + getName() + "(" + Strings.join( parameters, ", " ) + ")"; return returnType + " " + getName() + "(" + Strings.join( parameters, ", " ) + ")";

View File

@ -18,6 +18,7 @@
*/ */
package org.mapstruct.ap.model.assignment; package org.mapstruct.ap.model.assignment;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.mapstruct.ap.model.Assignment; import org.mapstruct.ap.model.Assignment;
import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.Type;
@ -38,9 +39,14 @@ public class LocalVarWrapper extends AssignmentWrapper {
@Override @Override
public List<Type> getExceptionTypes() { public List<Type> getExceptionTypes() {
List<Type> result = super.getExceptionTypes(); List<Type> parentExceptionTypes = super.getExceptionTypes();
for (Type exceptionTypeToExclude : exceptionTypesToExclude) { List<Type> result = new ArrayList<Type>( parentExceptionTypes );
result.remove( exceptionTypeToExclude ); for ( Type exceptionTypeToExclude : exceptionTypesToExclude ) {
for ( Type parentExceptionType : parentExceptionTypes ) {
if ( parentExceptionType.isAssignableTo( exceptionTypeToExclude ) ) {
result.remove( parentExceptionType );
}
}
} }
return result; return result;
} }

View File

@ -20,6 +20,7 @@ package org.mapstruct.ap.model.assignment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.mapstruct.ap.model.Assignment; import org.mapstruct.ap.model.Assignment;
@ -73,10 +74,12 @@ public class MethodReference extends MappingMethod implements Assignment, Factor
super( method ); super( method );
this.declaringMapper = declaringMapper; this.declaringMapper = declaringMapper;
this.contextParam = null; this.contextParam = null;
this.importTypes = targetType == null ? Set<Type> imported = new HashSet( method.getThrownTypes() );
Collections.<Type>emptySet() : if ( targetType != null ) {
Collections.<Type>singleton( targetType ); imported.add( targetType );
this.exceptionTypes = method.getExceptionTypes(); }
this.importTypes = Collections.<Type>unmodifiableSet( imported );
this.exceptionTypes = method.getThrownTypes();
} }
public MethodReference(BuiltInMethod method, ConversionContext contextParam) { public MethodReference(BuiltInMethod method, ConversionContext contextParam) {

View File

@ -18,6 +18,7 @@
*/ */
package org.mapstruct.ap.model.assignment; package org.mapstruct.ap.model.assignment;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.mapstruct.ap.model.Assignment; import org.mapstruct.ap.model.Assignment;
import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.Type;
@ -38,10 +39,16 @@ public class SetterWrapper extends AssignmentWrapper {
@Override @Override
public List<Type> getExceptionTypes() { public List<Type> getExceptionTypes() {
List<Type> result = super.getExceptionTypes(); List<Type> parentExceptionTypes = super.getExceptionTypes();
for (Type exceptionTypeToExclude : exceptionTypesToExclude) { List<Type> result = new ArrayList<Type>( parentExceptionTypes );
result.remove( exceptionTypeToExclude ); for ( Type exceptionTypeToExclude : exceptionTypesToExclude ) {
for ( Type parentExceptionType : parentExceptionTypes ) {
if ( parentExceptionType.isAssignableTo( exceptionTypeToExclude ) ) {
result.remove( parentExceptionType );
}
}
} }
return result; return result;
} }
} }

View File

@ -96,4 +96,11 @@ public interface Method {
* @return return type * @return return type
*/ */
Type getReturnType(); Type getReturnType();
/**
* Returns all exceptions thrown by this method
*
* @return exceptions thrown
*/
List<Type> getThrownTypes();
} }

View File

@ -351,7 +351,7 @@ public class SourceMethod implements Method {
return false; return false;
} }
public List<Type> getExceptionTypes() { public List<Type> getThrownTypes() {
return exceptionTypes; return exceptionTypes;
} }
} }

View File

@ -177,4 +177,9 @@ public abstract class BuiltInMethod implements Method {
public Accessibility getAccessibility() { public Accessibility getAccessibility() {
return Accessibility.PRIVATE; return Accessibility.PRIVATE;
} }
@Override
public List<Type> getThrownTypes() {
return Collections.emptyList();
}
} }

View File

@ -670,7 +670,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
} }
// target accessor is setter, so decorate assigmment as setter // target accessor is setter, so decorate assigmment as setter
assignment = new SetterWrapper( assignment, method.getExceptionTypes() ); assignment = new SetterWrapper( assignment, method.getThrownTypes() );
// decorate assigment with null check of source can be null (is not primitive) // decorate assigment with null check of source can be null (is not primitive)
if ( !sourceType.isPrimitive() ) { if ( !sourceType.isPrimitive() ) {
@ -736,7 +736,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
} }
// target accessor is setter, so decorate assigmment as setter // target accessor is setter, so decorate assigmment as setter
assignment = new SetterWrapper( assignment, method.getExceptionTypes() ); assignment = new SetterWrapper( assignment, method.getThrownTypes() );
FactoryMethod factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() ); FactoryMethod factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
return new IterableMappingMethod( method, assignment, factoryMethod ); return new IterableMappingMethod( method, assignment, factoryMethod );
@ -807,8 +807,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
FactoryMethod factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() ); FactoryMethod factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
keyAssignment = new LocalVarWrapper( keyAssignment, method.getExceptionTypes() ); keyAssignment = new LocalVarWrapper( keyAssignment, method.getThrownTypes() );
valueAssignment = new LocalVarWrapper( valueAssignment, method.getExceptionTypes() ); valueAssignment = new LocalVarWrapper( valueAssignment, method.getThrownTypes() );
return new MapMappingMethod( method, keyAssignment, valueAssignment, factoryMethod ); return new MapMappingMethod( method, keyAssignment, valueAssignment, factoryMethod );
} }

View File

@ -19,7 +19,7 @@
--> -->
@Override @Override
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>)<@exceptions/> { <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) <@throws/> {
if ( <#list sourceParameters as sourceParam>${sourceParam.name} == null<#if sourceParam_has_next> && </#if></#list> ) { if ( <#list sourceParameters as sourceParam>${sourceParam.name} == null<#if sourceParam_has_next> && </#if></#list> ) {
return<#if returnType.name != "void"> null</#if>; return<#if returnType.name != "void"> null</#if>;
} }
@ -43,4 +43,12 @@
return ${resultName}; return ${resultName};
</#if> </#if>
} }
<#macro exceptions><#if (exceptionTypes?size > 0)> throws </#if><#list exceptionTypes as exceptionType>${exceptionType.name}<#if exceptionType_has_next>, </#if></#list></#macro> <#macro throws>
<@compress single_line=true>
<#if (thrownTypes?size > 0)>throws </#if>
<#list thrownTypes as exceptionType>
<@includeModel object=exceptionType/>
<#if exceptionType_has_next>, </#if>
</#list>
</@compress>
</#macro>

View File

@ -19,6 +19,15 @@
--> -->
@Override @Override
public <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) { public <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) <@throws/> {
return delegate.${name}( <#list parameters as param>${param.name}<#if param_has_next>, </#if></#list> ); return delegate.${name}( <#list parameters as param>${param.name}<#if param_has_next>, </#if></#list> );
} }
<#macro throws>
<@compress single_line=true>
<#if (thrownTypes?size > 0)>throws </#if>
<#list thrownTypes as exceptionType>
<@includeModel object=exceptionType/>
<#if exceptionType_has_next>, </#if>
</#list>
</@compress>
</#macro>

View File

@ -19,7 +19,7 @@
--> -->
@Override @Override
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) { <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) <@throws/> {
if ( ${sourceParameter.name} == null ) { if ( ${sourceParameter.name} == null ) {
return<#if returnType.name != "void"> null</#if>; return<#if returnType.name != "void"> null</#if>;
} }
@ -39,3 +39,12 @@
return ${resultName}; return ${resultName};
</#if> </#if>
} }
<#macro throws>
<@compress single_line=true>
<#if (thrownTypes?size > 0)>throws </#if>
<#list thrownTypes as exceptionType>
<@includeModel object=exceptionType/>
<#if exceptionType_has_next>, </#if>
</#list>
</@compress>
</#macro>

View File

@ -19,7 +19,7 @@
--> -->
@Override @Override
<#lt>${accessibility.keyword} <@includeModel object=returnType /> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) { <#lt>${accessibility.keyword} <@includeModel object=returnType /> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) <@throws/> {
if ( ${sourceParameter.name} == null ) { if ( ${sourceParameter.name} == null ) {
return<#if returnType.name != "void"> null</#if>; return<#if returnType.name != "void"> null</#if>;
} }
@ -53,3 +53,12 @@
<#local result><@includeModel object=type/></#local> <#local result><@includeModel object=type/></#local>
<#return result> <#return result>
</#function> </#function>
<#macro throws>
<@compress single_line=true>
<#if (thrownTypes?size > 0)>throws </#if>
<#list thrownTypes as exceptionType>
<@includeModel object=exceptionType/>
<#if exceptionType_has_next>, </#if>
</#list>
</@compress>
</#macro>

View File

@ -18,7 +18,12 @@
*/ */
package org.mapstruct.ap.test.exceptions; package org.mapstruct.ap.test.exceptions;
import org.mapstruct.ap.test.exceptions.imports.TestException1;
import org.mapstruct.ap.test.exceptions.imports.TestExceptionBase;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
@ -34,27 +39,101 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
Target.class, Target.class,
SourceTargetMapper.class, SourceTargetMapper.class,
ExceptionTestMapper.class, ExceptionTestMapper.class,
ExceptionTestDecorator.class,
TestExceptionBase.class,
TestException1.class, TestException1.class,
TestException2.class } ) TestException2.class } )
@RunWith( AnnotationProcessorTestRunner.class ) @RunWith( AnnotationProcessorTestRunner.class )
public class ExceptionTest { public class ExceptionTest {
@Test(expected = RuntimeException.class) @Test( expected = RuntimeException.class )
@IssueKey( "198" ) @IssueKey( "198" )
public void shouldThrowRuntime() throws TestException2 { public void shouldThrowRuntimeInBeanMapping() throws TestException2 {
Source source = new Source(); Source source = new Source();
source.setSize( 1 ); source.setSize( 1 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE; SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.sourceToTarget( source ); sourceTargetMapper.sourceToTarget( source );
} }
@Test(expected = TestException2.class) @Test( expected = TestException2.class )
@IssueKey( "198" ) @IssueKey( "198" )
public void shouldThrowTestException2() throws TestException2 { public void shouldThrowTestException2InBeanMapping() throws TestException2 {
Source source = new Source(); Source source = new Source();
source.setSize( 2 ); source.setSize( 2 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE; SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.sourceToTarget( source ); sourceTargetMapper.sourceToTarget( source );
} }
@Test( expected = RuntimeException.class )
@IssueKey( "198" )
public void shouldThrowRuntimeInIterableMapping() throws TestException2 {
List<Integer> source = new ArrayList<Integer>();
source.add( 1 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.integerListToLongList( source );
}
@Test( expected = TestException2.class )
@IssueKey( "198" )
public void shouldThrowTestException2InIterableMapping() throws TestException2 {
List<Integer> source = new ArrayList<Integer>();
source.add( 2 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.integerListToLongList( source );
}
@Test( expected = RuntimeException.class )
@IssueKey( "198" )
public void shouldThrowRuntimeInMapKeyMapping() throws TestException2 {
Map<Integer, String> source = new HashMap<Integer, String>();
source.put( 1, "test" );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.integerKeyMapToLongKeyMap( source );
}
@Test( expected = TestException2.class )
@IssueKey( "198" )
public void shouldThrowTestException2InMapKeyMapping() throws TestException2 {
Map<Integer, String> source = new HashMap<Integer, String>();
source.put( 2, "test" );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.integerKeyMapToLongKeyMap( source );
}
@Test( expected = RuntimeException.class )
@IssueKey( "198" )
public void shouldThrowRuntimeInMapValueMapping() throws TestException2 {
Map<String, Integer> source = new HashMap<String, Integer>();
source.put( "test", 1 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.integerValueMapToLongValueMap( source );
}
@Test( expected = TestException2.class )
@IssueKey( "198" )
public void shouldThrowTestException2InMapValueMapping() throws TestException2 {
Map<String, Integer> source = new HashMap<String, Integer>();
source.put( "test", 2 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.integerValueMapToLongValueMap( source );
}
@Test( expected = RuntimeException.class )
@IssueKey( "198" )
public void shouldThrowRuntimeInBeanMappingViaBaseException() throws TestExceptionBase {
Source source = new Source();
source.setSize( 1 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.sourceToTargetViaBaseException( source );
}
@Test( expected = TestException2.class )
@IssueKey( "198" )
public void shouldThrowTestException2InBeanMappingViaBaseException() throws TestExceptionBase {
Source source = new Source();
source.setSize( 2 );
SourceTargetMapper sourceTargetMapper = SourceTargetMapper.INSTANCE;
sourceTargetMapper.sourceToTargetViaBaseException( source );
}
} }

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2014 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.exceptions;
public abstract class ExceptionTestDecorator implements SourceTargetMapper {
private final SourceTargetMapper delegate;
public ExceptionTestDecorator(SourceTargetMapper delegate) {
this.delegate = delegate;
}
}

View File

@ -18,6 +18,8 @@
*/ */
package org.mapstruct.ap.test.exceptions; package org.mapstruct.ap.test.exceptions;
import org.mapstruct.ap.test.exceptions.imports.TestException1;
/** /**
* @author Sjaak Derksen * @author Sjaak Derksen
* *
@ -33,4 +35,14 @@ public class ExceptionTestMapper {
} }
return new Long(size); return new Long(size);
} }
public Long toLong(Integer size) throws TestException1, TestException2 {
if ( size == 1 ) {
throw new TestException1();
}
else if ( size == 2 ) {
throw new TestException2();
}
return new Long(size);
}
} }

View File

@ -19,6 +19,10 @@
package org.mapstruct.ap.test.exceptions; package org.mapstruct.ap.test.exceptions;
import org.mapstruct.ap.test.exceptions.imports.TestExceptionBase;
import java.util.List;
import java.util.Map;
import org.mapstruct.DecoratedWith;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -27,10 +31,19 @@ import org.mapstruct.factory.Mappers;
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@Mapper( uses = ExceptionTestMapper.class ) @Mapper( uses = ExceptionTestMapper.class )
@DecoratedWith( ExceptionTestDecorator.class )
public interface SourceTargetMapper { public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
Target sourceToTarget(Source source) throws TestException2; Target sourceToTarget(Source source) throws TestException2;
List<Long> integerListToLongList(List<Integer> sizes) throws TestException2;
Map<Long, String> integerKeyMapToLongKeyMap(Map<Integer, String> sizes) throws TestException2;
Map<String, Long> integerValueMapToLongValueMap(Map<String, Integer> sizes) throws TestException2;
Target sourceToTargetViaBaseException(Source source) throws TestExceptionBase;
} }

View File

@ -18,9 +18,11 @@
*/ */
package org.mapstruct.ap.test.exceptions; package org.mapstruct.ap.test.exceptions;
import org.mapstruct.ap.test.exceptions.imports.TestExceptionBase;
/** /**
* *
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
public class TestException2 extends Exception { public class TestException2 extends TestExceptionBase {
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.mapstruct.ap.test.exceptions; package org.mapstruct.ap.test.exceptions.imports;
/** /**
* *

View File

@ -0,0 +1,26 @@
/**
* Copyright 2012-2014 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.exceptions.imports;
/**
*
* @author Sjaak Derksen
*/
public class TestExceptionBase extends Exception {
}