#636 - fix - default methods (Java 8) do not work anymore

This commit is contained in:
Ivo Smid 2015-09-05 17:32:00 +02:00 committed by sjaakd
parent c43b495863
commit a15a67ff47
16 changed files with 420 additions and 34 deletions

View File

@ -0,0 +1,31 @@
/**
* Copyright 2012-2015 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.bugs._636;
public class Bar {
private final String id;
public Bar(String id) {
this.id = id;
}
public String getId() {
return id;
}
}

View File

@ -0,0 +1,31 @@
/**
* Copyright 2012-2015 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.bugs._636;
public class Foo {
private final long id;
public Foo(long id) {
this.id = id;
}
public long getId() {
return id;
}
}

View File

@ -0,0 +1,34 @@
/**
* Copyright 2012-2015 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.bugs._636;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public class MyMapper {
public BigDecimal mapBigIntToDecimal(BigInteger source) {
return source == null ? null : new BigDecimal( source );
}
}

View File

@ -0,0 +1,45 @@
/**
* Copyright 2012-2015 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.bugs._636;
import java.math.BigInteger;
public class Source {
private final long idFoo;
private final String idBar;
private final BigInteger number;
public Source(long idFoo, String idBar, BigInteger number) {
this.idFoo = idFoo;
this.idBar = idBar;
this.number = number;
}
public long getIdFoo() {
return idFoo;
}
public String getIdBar() {
return idBar;
}
public BigInteger getNumber() {
return number;
}
}

View File

@ -0,0 +1,44 @@
/**
* Copyright 2012-2015 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.bugs._636;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper(uses = MyMapper.class)
public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mappings({
@Mapping(source = "idFoo", target = "foo"),
@Mapping(source = "idBar", target = "bar"),
@Mapping(source = "number", target = "number")
})
Target mapSourceToTarget(Source source);
default Foo fooFromId(long id) {
return new Foo(id);
}
static Bar barFromId(String id) {
return new Bar(id);
}
}

View File

@ -0,0 +1,51 @@
/**
* Copyright 2012-2015 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.bugs._636;
import java.math.BigDecimal;
public class Target {
private Foo foo;
private Bar bar;
private BigDecimal number;
public Foo getFoo() {
return foo;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
public BigDecimal getNumber() {
return number;
}
public void setNumber(BigDecimal number) {
this.number = number;
}
}

View File

@ -0,0 +1,48 @@
/**
* Copyright 2012-2015 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.bugs._636;
import java.math.BigInteger;
import org.junit.Test;
import static org.fest.assertions.Assertions.assertThat;
public class Issue636Test {
@Test
public void shouldMapDataFromJava8Interface() {
final long idFoo = 123;
final String idBar = "Bar456";
final BigInteger number = BigInteger.valueOf( 789L );
final Source source = new Source( idFoo, idBar, number );
final Target target = SourceTargetMapper.INSTANCE.mapSourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isNotNull();
assertThat( target.getFoo().getId() ).isEqualTo( idFoo );
assertThat( target.getBar() ).isNotNull();
assertThat( target.getBar().getId() ).isEqualTo( idBar );
assertThat( target.getNumber() ).isNotNull();
assertThat( target.getNumber().toBigInteger() ).isEqualTo( number );
}
}

View File

@ -47,6 +47,7 @@ public abstract class MappingMethod extends ModelElement {
private final Accessibility accessibility; private final Accessibility accessibility;
private final List<Type> thrownTypes; private final List<Type> thrownTypes;
private final boolean isStatic; private final boolean isStatic;
private final Type staticMethodFromInterfaceType;
private final String resultName; private final String resultName;
private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithMappingTarget; private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithMappingTarget;
private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithoutMappingTarget; private final List<LifecycleCallbackMethodReference> beforeMappingReferencesWithoutMappingTarget;
@ -69,6 +70,7 @@ public abstract class MappingMethod extends ModelElement {
this.accessibility = method.getAccessibility(); this.accessibility = method.getAccessibility();
this.thrownTypes = method.getThrownTypes(); this.thrownTypes = method.getThrownTypes();
this.isStatic = method.isStatic(); this.isStatic = method.isStatic();
this.staticMethodFromInterfaceType = method.getStaticMethodFromInterfaceType();
this.resultName = initResultName( existingVariableNames ); this.resultName = initResultName( existingVariableNames );
this.beforeMappingReferencesWithMappingTarget = filterMappingTarget( beforeMappingReferences, true ); this.beforeMappingReferencesWithMappingTarget = filterMappingTarget( beforeMappingReferences, true );
this.beforeMappingReferencesWithoutMappingTarget = filterMappingTarget( beforeMappingReferences, false ); this.beforeMappingReferencesWithoutMappingTarget = filterMappingTarget( beforeMappingReferences, false );
@ -144,6 +146,10 @@ public abstract class MappingMethod extends ModelElement {
return isStatic; return isStatic;
} }
public Type getStaticMethodFromInterfaceType() {
return staticMethodFromInterfaceType;
}
@Override @Override
public Set<Type> getImportTypes() { public Set<Type> getImportTypes() {
Set<Type> types = new HashSet<Type>(); Set<Type> types = new HashSet<Type>();
@ -154,6 +160,9 @@ public abstract class MappingMethod extends ModelElement {
types.add( getReturnType() ); types.add( getReturnType() );
types.addAll( thrownTypes ); types.addAll( thrownTypes );
if ( staticMethodFromInterfaceType != null ) {
types.add( staticMethodFromInterfaceType );
}
return types; return types;
} }

View File

@ -192,6 +192,16 @@ public class ForgedMethod implements Method {
return false; return false;
} }
@Override
public boolean isDefault() {
return false;
}
@Override
public Type getStaticMethodFromInterfaceType() {
return null;
}
@Override @Override
public MapperConfiguration getMapperConfiguration() { public MapperConfiguration getMapperConfiguration() {
return null; return null;

View File

@ -144,6 +144,20 @@ public interface Method {
*/ */
boolean isStatic(); boolean isStatic();
/**
* Whether this method is Java 8 default method
*
* @return true when Java 8 default method
*/
boolean isDefault();
/**
* Returns method's enclosing type if method is Java 8 static method
*
* @return type of static method from Java 8 interface
*/
Type getStaticMethodFromInterfaceType();
/** /**
* *
* @return the mapper config when this method needs to be implemented * @return the mapper config when this method needs to be implemented

View File

@ -66,6 +66,8 @@ public class SourceMethod implements Method {
private final MapperConfiguration config; private final MapperConfiguration config;
private final MappingOptions mappingOptions; private final MappingOptions mappingOptions;
private final List<SourceMethod> prototypeMethods; private final List<SourceMethod> prototypeMethods;
private final boolean defaultMethod;
private final Type staticMethodFromInterfaceType;
private List<Parameter> sourceParameters; private List<Parameter> sourceParameters;
@ -89,6 +91,8 @@ public class SourceMethod implements Method {
private FormattingMessager messager = null; private FormattingMessager messager = null;
private MapperConfiguration mapperConfig = null; private MapperConfiguration mapperConfig = null;
private List<SourceMethod> prototypeMethods = Collections.emptyList(); private List<SourceMethod> prototypeMethods = Collections.emptyList();
private boolean defaultMethod;
private Type staticMethodFromInterfaceType;
public Builder() { public Builder() {
} }
@ -163,6 +167,16 @@ public class SourceMethod implements Method {
return this; return this;
} }
public Builder setDefaultMethod(boolean defaultMethod) {
this.defaultMethod = defaultMethod;
return this;
}
public Builder setStaticMethodFromInterfaceType(Type staticMethodFromInterfaceType) {
this.staticMethodFromInterfaceType = staticMethodFromInterfaceType;
return this;
}
public SourceMethod build() { public SourceMethod build() {
MappingOptions mappingOptions MappingOptions mappingOptions
@ -178,7 +192,9 @@ public class SourceMethod implements Method {
typeUtils, typeUtils,
typeFactory, typeFactory,
mapperConfig, mapperConfig,
prototypeMethods prototypeMethods,
defaultMethod,
staticMethodFromInterfaceType
); );
if ( mappings != null ) { if ( mappings != null ) {
@ -194,8 +210,9 @@ public class SourceMethod implements Method {
@SuppressWarnings("checkstyle:parameternumber") @SuppressWarnings("checkstyle:parameternumber")
private SourceMethod(Type declaringMapper, ExecutableElement executable, List<Parameter> parameters, private SourceMethod(Type declaringMapper, ExecutableElement executable, List<Parameter> parameters,
Type returnType, List<Type> exceptionTypes, MappingOptions mappingOptions, Types typeUtils, Type returnType, List<Type> exceptionTypes, MappingOptions mappingOptions, Types typeUtils,
TypeFactory typeFactory, MapperConfiguration config, List<SourceMethod> prototypeMethods) { TypeFactory typeFactory, MapperConfiguration config, List<SourceMethod> prototypeMethods,
boolean defaultMethod, Type staticMethodFromInterfaceType) {
this.declaringMapper = declaringMapper; this.declaringMapper = declaringMapper;
this.executable = executable; this.executable = executable;
this.parameters = parameters; this.parameters = parameters;
@ -212,6 +229,8 @@ public class SourceMethod implements Method {
this.typeFactory = typeFactory; this.typeFactory = typeFactory;
this.config = config; this.config = config;
this.prototypeMethods = prototypeMethods; this.prototypeMethods = prototypeMethods;
this.defaultMethod = defaultMethod;
this.staticMethodFromInterfaceType = staticMethodFromInterfaceType;
} }
private Parameter determineMappingTargetParameter(Iterable<Parameter> parameters) { private Parameter determineMappingTargetParameter(Iterable<Parameter> parameters) {
@ -511,6 +530,15 @@ public class SourceMethod implements Method {
return executable.getModifiers().contains( Modifier.STATIC ); return executable.getModifiers().contains( Modifier.STATIC );
} }
@Override
public boolean isDefault() {
return defaultMethod;
}
@Override
public Type getStaticMethodFromInterfaceType() {
return staticMethodFromInterfaceType;
}
@Override @Override
public MapperConfiguration getMapperConfiguration() { public MapperConfiguration getMapperConfiguration() {

View File

@ -239,6 +239,16 @@ public abstract class BuiltInMethod implements Method {
return false; return false;
} }
@Override
public boolean isDefault() {
return false;
}
@Override
public Type getStaticMethodFromInterfaceType() {
return null;
}
@Override @Override
public MapperConfiguration getMapperConfiguration() { public MapperConfiguration getMapperConfiguration() {
return null; return null;

View File

@ -187,7 +187,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
} }
} }
Type declaringMapper = mappingMethod.getDeclaringMapper(); Type declaringMapper = mappingMethod.getDeclaringMapper();
if ( implementationRequired ) { if ( implementationRequired && !( mappingMethod.isDefault() || mappingMethod.isStatic()) ) {
if ( ( declaringMapper == null ) || declaringMapper.equals( typeFactory.getType( element ) ) ) { if ( ( declaringMapper == null ) || declaringMapper.equals( typeFactory.getType( element ) ) ) {
mappingMethods.add( new DelegatingMethod( mappingMethod ) ); mappingMethods.add( new DelegatingMethod( mappingMethod ) );
} }

View File

@ -23,7 +23,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier; import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
@ -87,7 +87,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
} }
List<SourceMethod> prototypeMethods = List<SourceMethod> prototypeMethods =
retrievePrototypeMethods( mapperConfig.getMapperConfigMirror(), mapperConfig ); retrievePrototypeMethods( mapperConfig.getMapperConfigMirror(), mapperConfig, mapperTypeElement );
return retrieveMethods( mapperTypeElement, mapperTypeElement, mapperConfig, prototypeMethods ); return retrieveMethods( mapperTypeElement, mapperTypeElement, mapperConfig, prototypeMethods );
} }
@ -96,7 +96,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
return 1; return 1;
} }
private List<SourceMethod> retrievePrototypeMethods(TypeMirror typeMirror, MapperConfiguration mapperConfig) { private List<SourceMethod> retrievePrototypeMethods(TypeMirror typeMirror, MapperConfiguration mapperConfig,
TypeElement mapperTypeElement) {
if ( typeMirror == null || typeMirror.getKind() == TypeKind.VOID ) { if ( typeMirror == null || typeMirror.getKind() == TypeKind.VOID ) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -119,7 +120,9 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
parameters, parameters,
containsTargetTypeParameter, containsTargetTypeParameter,
mapperConfig, mapperConfig,
prototypeMethods ); prototypeMethods,
mapperTypeElement
);
if ( method != null ) { if ( method != null ) {
methods.add( method ); methods.add( method );
@ -193,7 +196,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
parameters, parameters,
containsTargetTypeParameter, containsTargetTypeParameter,
mapperConfig, mapperConfig,
prototypeMethods ); prototypeMethods,
mapperToImplement);
} }
//otherwise add reference to existing mapper method //otherwise add reference to existing mapper method
else if ( isValidReferencedMethod( parameters ) || isValidFactoryMethod( parameters, returnType ) else if ( isValidReferencedMethod( parameters ) || isValidFactoryMethod( parameters, returnType )
@ -209,7 +213,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
List<Parameter> parameters, List<Parameter> parameters,
boolean containsTargetTypeParameter, boolean containsTargetTypeParameter,
MapperConfiguration mapperConfig, MapperConfiguration mapperConfig,
List<SourceMethod> prototypeMethods) { List<SourceMethod> prototypeMethods,
TypeElement mapperToImplement) {
Type returnType = typeFactory.getReturnType( methodType ); Type returnType = typeFactory.getReturnType( methodType );
List<Type> exceptionTypes = typeFactory.getThrownTypes( methodType ); List<Type> exceptionTypes = typeFactory.getThrownTypes( methodType );
List<Parameter> sourceParameters = extractSourceParameters( parameters ); List<Parameter> sourceParameters = extractSourceParameters( parameters );
@ -234,19 +239,25 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
.setParameters( parameters ) .setParameters( parameters )
.setReturnType( returnType ) .setReturnType( returnType )
.setExceptionTypes( exceptionTypes ) .setExceptionTypes( exceptionTypes )
.setMappings( getMappings( method) ) .setMappings( getMappings( method ) )
.setIterableMapping( IterableMapping.fromPrism( .setIterableMapping(
IterableMappingPrism.getInstanceOn( method ), method, messager ) ) IterableMapping.fromPrism(
IterableMappingPrism.getInstanceOn( method ), method, messager
)
)
.setMapMapping( .setMapMapping(
MapMapping.fromPrism( MapMappingPrism.getInstanceOn( method ), method, messager ) ) MapMapping.fromPrism( MapMappingPrism.getInstanceOn( method ), method, messager )
)
.setBeanMapping( .setBeanMapping(
BeanMapping.fromPrism( BeanMappingPrism.getInstanceOn( method ), method, messager ) ) BeanMapping.fromPrism( BeanMappingPrism.getInstanceOn( method ), method, messager )
)
.setTypeUtils( typeUtils ) .setTypeUtils( typeUtils )
.setMessager( messager ) .setMessager( messager )
.setTypeFactory( typeFactory ) .setTypeFactory( typeFactory )
.setMapperConfiguration( mapperConfig ) .setMapperConfiguration( mapperConfig )
.setPrototypeMethods( prototypeMethods ) .setPrototypeMethods( prototypeMethods )
.build(); .setDefaultMethod( Executables.isInterfaceDefaultMethod( method, mapperToImplement ) )
.build();
} }
private SourceMethod getReferencedMethod(TypeElement usedMapper, ExecutableType methodType, private SourceMethod getReferencedMethod(TypeElement usedMapper, ExecutableType methodType,
@ -256,20 +267,33 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
List<Type> exceptionTypes = typeFactory.getThrownTypes( methodType ); List<Type> exceptionTypes = typeFactory.getThrownTypes( methodType );
Type usedMapperAsType = typeFactory.getType( usedMapper ); Type usedMapperAsType = typeFactory.getType( usedMapper );
Type mapperToImplementAsType = typeFactory.getType( mapperToImplement ); Type mapperToImplementAsType = typeFactory.getType( mapperToImplement );
Type staticMethodFromInterfaceType = findStaticMethodFromInterfaceType( method );
if ( !mapperToImplementAsType.canAccess( usedMapperAsType, method ) ) { if ( !mapperToImplementAsType.canAccess( usedMapperAsType, method ) ) {
return null; return null;
} }
return new SourceMethod.Builder() return new SourceMethod.Builder()
.setDeclaringMapper( usedMapper.equals( mapperToImplement ) ? null : usedMapperAsType ) .setDeclaringMapper( usedMapper.equals( mapperToImplement ) ? null : usedMapperAsType )
.setExecutable( method ) .setExecutable( method )
.setParameters( parameters ) .setParameters( parameters )
.setReturnType( returnType ) .setReturnType( returnType )
.setExceptionTypes( exceptionTypes ) .setExceptionTypes( exceptionTypes )
.setTypeUtils( typeUtils ) .setTypeUtils( typeUtils )
.setTypeFactory( typeFactory ) .setTypeFactory( typeFactory )
.build(); .setDefaultMethod( Executables.isInterfaceDefaultMethod( method, mapperToImplement ) )
.setStaticMethodFromInterfaceType( staticMethodFromInterfaceType )
.build();
}
private Type findStaticMethodFromInterfaceType(ExecutableElement method) {
Element enclosingElement = method.getEnclosingElement();
boolean staticMethodFromInterface = ( enclosingElement.getKind().isInterface() &&
Executables.isStaticFromInterfaceMethod(
method, ( (TypeElement) enclosingElement )
)
);
return staticMethodFromInterface ? typeFactory.getType( enclosingElement.asType() ) : null;
} }
private boolean isValidLifecycleCallbackMethod(ExecutableElement method, Type returnType) { private boolean isValidLifecycleCallbackMethod(ExecutableElement method, Type returnType) {

View File

@ -187,9 +187,7 @@ public class Executables {
List<ExecutableElement> methodsToAdd, TypeElement parentType) { List<ExecutableElement> methodsToAdd, TypeElement parentType) {
List<ExecutableElement> safeToAdd = new ArrayList<ExecutableElement>( methodsToAdd.size() ); List<ExecutableElement> safeToAdd = new ArrayList<ExecutableElement>( methodsToAdd.size() );
for ( ExecutableElement toAdd : methodsToAdd ) { for ( ExecutableElement toAdd : methodsToAdd ) {
if ( isNotStaticMethodInInterface( toAdd, parentType ) if ( isNotObjectEquals( toAdd )
&& isNotInterfaceDefaultMethod( toAdd, parentType )
&& isNotObjectEquals( toAdd )
&& wasNotYetOverridden( elementUtils, alreadyCollected, toAdd, parentType ) ) { && wasNotYetOverridden( elementUtils, alreadyCollected, toAdd, parentType ) ) {
safeToAdd.add( toAdd ); safeToAdd.add( toAdd );
} }
@ -198,16 +196,16 @@ public class Executables {
alreadyCollected.addAll( 0, safeToAdd ); alreadyCollected.addAll( 0, safeToAdd );
} }
private static boolean isNotStaticMethodInInterface(ExecutableElement element, TypeElement parentType) { public static boolean isInterfaceDefaultMethod(ExecutableElement element, TypeElement parentType) {
return !( parentType.getKind().isInterface() && return parentType.getKind().isInterface() &&
element.getKind() == ElementKind.METHOD && element.getKind() == ElementKind.METHOD &&
element.getModifiers().containsAll( Arrays.asList( Modifier.PUBLIC, Modifier.STATIC ) ) ); isDefaultMethod( element );
} }
private static boolean isNotInterfaceDefaultMethod(ExecutableElement element, TypeElement parentType) { public static boolean isStaticFromInterfaceMethod(ExecutableElement element, TypeElement parentType) {
return !( parentType.getKind().isInterface() && return parentType.getKind().isInterface() &&
element.getKind() == ElementKind.METHOD && element.getKind() == ElementKind.METHOD &&
isDefaultMethod( element ) ); element.getModifiers().containsAll( Arrays.asList( Modifier.PUBLIC, Modifier.STATIC ) );
} }
/** /**

View File

@ -20,7 +20,16 @@
--> -->
<@compress single_line=true> <@compress single_line=true>
<#-- method is either internal to the mapper class, or external (via uses) declaringMapper!=null --> <#-- method is either internal to the mapper class, or external (via uses) declaringMapper!=null -->
<#if declaringMapper??><#if static><@includeModel object=declaringMapper.type/><#else>${mapperVariableName}</#if>.</#if>${name}<#if (parameters?size > 0)>( <@arguments/> )<#else>()</#if> <#if declaringMapper??><#if static><@includeModel object=declaringMapper.type/><#else>${mapperVariableName}</#if>.<@params/>
<#elseif staticMethodFromInterfaceType??><@includeModel object=staticMethodFromInterfaceType/>.<@params/>
<#else>
<@params/>
</#if>
<#macro params>
<@compress>
${name}<#if (parameters?size > 0)>( <@arguments/> )<#else>()</#if>
</@compress>
</#macro>
<#macro arguments> <#macro arguments>
<#list parameters as param> <#list parameters as param>
<#if param.targetType> <#if param.targetType>