From c0438c1d1525baae9a5dfa97457d0ff36d822cc0 Mon Sep 17 00:00:00 2001 From: sjaakd Date: Sat, 20 Dec 2014 19:41:26 +0100 Subject: [PATCH] #383 introduction of @InheritConfiguration to align update with create methods (several sources) --- .../ap/model/source/SourceMethod.java | 45 ++++++++++++++++++ .../ap/processor/MapperCreationProcessor.java | 2 +- .../template/InheritConfigurationTest.java | 28 +++++++++++ .../SourceTargetMapperSeveralArgs.java | 46 +++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/template/SourceTargetMapperSeveralArgs.java diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/SourceMethod.java b/processor/src/main/java/org/mapstruct/ap/model/source/SourceMethod.java index 17734ec91..9e5b82629 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/SourceMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/SourceMethod.java @@ -287,6 +287,39 @@ public class SourceMethod implements Method { && equals( getResultType(), method.getResultType() ); } + public boolean isSimilar(SourceMethod method) { + Map test = new HashMap(); + + // check how many times a type occurs + for (Parameter sourceParam : method.getSourceParameters() ) { + Type sourceType = sourceParam.getType(); + if ( !test.containsKey( sourceType ) ) { + test.put( sourceType, 0 ); + } + increase( sourceType, test ); + } + + // check if this method also contains the same time each parameter type. + for (Parameter sourceParam : getSourceParameters() ) { + Type sourceType = sourceParam.getType(); + if ( !test.containsKey( sourceType ) ) { + // method contains a different parameter type than this + return false; + } + decrease( sourceType, test ); + } + + // now, if they match they should have the same source parameter types each + for ( Integer count : test.values() ) { + if ( count != 0 ) { + return false; + } + } + + // finally check the return type. + return equals( getResultType(), method.getResultType() ); + } + /** * {@inheritDoc} {@link Method} */ @@ -462,4 +495,16 @@ public class SourceMethod implements Method { getMappings().putAll( newMappings ); } } + + private void increase(Type key, Map test) { + Integer count = test.get( key ); + count++; + test.put( key, count ); + } + + private void decrease(Type key, Map test) { + Integer count = test.get( key ); + count--; + test.put( key, count ); + } } diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index 5f4c18b7d..39f66f1d5 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -453,7 +453,7 @@ public class MapperCreationProcessor implements ModelElementProcessor candidates = new ArrayList(); for ( SourceMethod oneMethod : rawMethods ) { // method must be similar but not equal - if ( oneMethod.isSame( method ) && !( oneMethod.equals( method ) ) ) { + if ( oneMethod.isSimilar( method ) && !( oneMethod.equals( method ) ) ) { candidates.add( oneMethod ); } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/template/InheritConfigurationTest.java b/processor/src/test/java/org/mapstruct/ap/test/template/InheritConfigurationTest.java index 4a9c86319..d6fd44472 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/template/InheritConfigurationTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/template/InheritConfigurationTest.java @@ -94,6 +94,34 @@ public class InheritConfigurationTest { } + @Test + @WithClasses({ SourceTargetMapperSeveralArgs.class }) + public void shouldInheritConfigurationSeveralArgs() { + + Source source = new Source(); + source.setStringPropX( "1" ); + source.setIntegerPropX( 2 ); + source.setNestedSourceProp( new NestedSource("nested") ); + + Target createdTarget = SourceTargetMapperSeveralArgs.INSTANCE.forwardCreate( source, "constant", "expression" ); + assertThat( createdTarget ).isNotNull(); + assertThat( createdTarget.getStringPropY() ).isEqualTo( "1" ); + assertThat( createdTarget.getIntegerPropY() ).isEqualTo( 2 ); + assertThat( createdTarget.getNestedResultProp() ).isEqualTo( "nested"); + assertThat( createdTarget.getExpressionProp() ).isEqualTo( "expression" ); + assertThat( createdTarget.getConstantProp() ).isEqualTo( "constant" ); + + Target updatedTarget = new Target(); + SourceTargetMapperSeveralArgs.INSTANCE.forwardUpdate( source, "constant", "expression", updatedTarget ); + assertThat( updatedTarget ).isNotNull(); + assertThat( updatedTarget.getStringPropY() ).isEqualTo( "1" ); + assertThat( updatedTarget.getIntegerPropY() ).isEqualTo( 2 ); + assertThat( updatedTarget.getNestedResultProp() ).isEqualTo( "nested" ); + assertThat( updatedTarget.getExpressionProp() ).isEqualTo( "expression" ); + assertThat( updatedTarget.getConstantProp() ).isEqualTo( "constant" ); + + } + @Test @WithClasses({ SourceTargetMapperAmbiguous1.class }) @ExpectedCompilationOutcome( diff --git a/processor/src/test/java/org/mapstruct/ap/test/template/SourceTargetMapperSeveralArgs.java b/processor/src/test/java/org/mapstruct/ap/test/template/SourceTargetMapperSeveralArgs.java new file mode 100644 index 000000000..c2f2f43e9 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/template/SourceTargetMapperSeveralArgs.java @@ -0,0 +1,46 @@ +/** + * 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.template; + +import org.mapstruct.InheritConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +/** + * @author Sjaak Derksen + */ +@Mapper +public interface SourceTargetMapperSeveralArgs { + + SourceTargetMapperSeveralArgs INSTANCE = Mappers.getMapper( SourceTargetMapperSeveralArgs.class ); + + @Mappings({ + @Mapping(target = "stringPropY", source = "source.stringPropX"), + @Mapping(target = "integerPropY", source = "source.integerPropX"), + @Mapping(target = "nestedResultProp", source = "source.nestedSourceProp.nested") + }) + Target forwardCreate(Source source, String constantProp, String expressionProp); + + @InheritConfiguration + void forwardUpdate(Source source, String constantProp, String expressionProp, @MappingTarget Target target); + +}