mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#777 Set initial capacity for new collection / map element in collection / map mappings
This commit is contained in:
parent
763deaa917
commit
15133d5a0f
@ -42,6 +42,7 @@ public abstract class ContainerMappingMethod extends NormalTypeMappingMethod {
|
||||
private final SelectionParameters selectionParameters;
|
||||
private final String index1Name;
|
||||
private final String index2Name;
|
||||
private IterableCreation iterableCreation;
|
||||
|
||||
ContainerMappingMethod(Method method, Collection<String> existingVariables, Assignment parameterAssignment,
|
||||
MethodReference factoryMethod, boolean mapNullToDefault, String loopVariableName,
|
||||
@ -67,6 +68,13 @@ public abstract class ContainerMappingMethod extends NormalTypeMappingMethod {
|
||||
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
||||
}
|
||||
|
||||
public IterableCreation getIterableCreation() {
|
||||
if ( iterableCreation == null ) {
|
||||
iterableCreation = IterableCreation.create( this, getSourceParameter() );
|
||||
}
|
||||
return iterableCreation;
|
||||
}
|
||||
|
||||
public Assignment getElementAssignment() {
|
||||
return elementAssignment;
|
||||
}
|
||||
@ -77,6 +85,10 @@ public abstract class ContainerMappingMethod extends NormalTypeMappingMethod {
|
||||
if ( elementAssignment != null ) {
|
||||
types.addAll( elementAssignment.getImportTypes() );
|
||||
}
|
||||
|
||||
if ( iterableCreation != null ) {
|
||||
types.addAll( iterableCreation.getImportTypes() );
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* 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.internal.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ModelElement;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
/**
|
||||
* Model element that can be used to create a type of {@link Iterable} or {@link java.util.Map}. If an implementation
|
||||
* type is used and the target type has a constructor with {@link int} as parameter and the source parameter is of
|
||||
* {@link java.util.Collection}, {@link java.util.Map} or {@code Array} type then MapStruct will use that constructor
|
||||
* with the {@code size} / {@code length} from the source parameter.
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class IterableCreation extends ModelElement {
|
||||
|
||||
private final Type resultType;
|
||||
private final Parameter sourceParameter;
|
||||
private final MethodReference factoryMethod;
|
||||
private final boolean canUseSize;
|
||||
private final boolean loadFactorAdjustment;
|
||||
|
||||
private IterableCreation(Type resultType, Parameter sourceParameter, MethodReference factoryMethod) {
|
||||
this.resultType = resultType;
|
||||
this.sourceParameter = sourceParameter;
|
||||
this.factoryMethod = factoryMethod;
|
||||
this.canUseSize = ( sourceParameter.getType().isCollectionOrMapType() ||
|
||||
sourceParameter.getType().isArrayType() )
|
||||
&& resultType.getImplementation() != null && resultType.getImplementation().hasInitialCapacityConstructor();
|
||||
this.loadFactorAdjustment = this.canUseSize && resultType.getImplementation().isLoadFactorAdjustment();
|
||||
|
||||
}
|
||||
|
||||
public static IterableCreation create(NormalTypeMappingMethod mappingMethod, Parameter sourceParameter) {
|
||||
return new IterableCreation( mappingMethod.getResultType(), sourceParameter, mappingMethod.getFactoryMethod() );
|
||||
}
|
||||
|
||||
public Type getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
public Parameter getSourceParameter() {
|
||||
return sourceParameter;
|
||||
}
|
||||
|
||||
public MethodReference getFactoryMethod() {
|
||||
return this.factoryMethod;
|
||||
}
|
||||
|
||||
public boolean isCanUseSize() {
|
||||
return canUseSize;
|
||||
}
|
||||
|
||||
public boolean isLoadFactorAdjustment() {
|
||||
return loadFactorAdjustment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Type> getImportTypes() {
|
||||
Set<Type> types = new HashSet<Type>();
|
||||
if ( factoryMethod == null && resultType.getImplementationType() != null ) {
|
||||
types.addAll( resultType.getImplementationType().getImportTypes() );
|
||||
}
|
||||
return types;
|
||||
}
|
||||
}
|
@ -47,6 +47,7 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
|
||||
private final Assignment keyAssignment;
|
||||
private final Assignment valueAssignment;
|
||||
private IterableCreation iterableCreation;
|
||||
|
||||
public static class Builder extends AbstractMappingMethodBuilder<Builder, MapMappingMethod> {
|
||||
|
||||
@ -268,6 +269,10 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
types.addAll( valueAssignment.getImportTypes() );
|
||||
}
|
||||
|
||||
if ( iterableCreation != null ) {
|
||||
types.addAll( iterableCreation.getImportTypes() );
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
@ -291,4 +296,11 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
|
||||
getParameterNames()
|
||||
);
|
||||
}
|
||||
|
||||
public IterableCreation getIterableCreation() {
|
||||
if ( iterableCreation == null ) {
|
||||
iterableCreation = IterableCreation.create( this, getSourceParameter() );
|
||||
}
|
||||
return iterableCreation;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* 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.internal.model.common;
|
||||
|
||||
/**
|
||||
* This is a wrapper class for the Implementation types that are used within MapStruct. It contains all the
|
||||
* information needed for an Iterable creation
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class ImplementationType {
|
||||
|
||||
private final Type type;
|
||||
private final boolean initialCapacityConstructor;
|
||||
private final boolean loadFactorAdjustment;
|
||||
|
||||
private ImplementationType(Type type, boolean initialCapacityConstructor, boolean loadFactorAdjustment) {
|
||||
this.type = type;
|
||||
this.initialCapacityConstructor = initialCapacityConstructor;
|
||||
this.loadFactorAdjustment = loadFactorAdjustment;
|
||||
}
|
||||
|
||||
public static ImplementationType withDefaultConstructor(Type type) {
|
||||
return new ImplementationType( type, false, false );
|
||||
}
|
||||
|
||||
public static ImplementationType withInitialCapacity(Type type) {
|
||||
return new ImplementationType( type, true, false );
|
||||
}
|
||||
|
||||
public static ImplementationType withLoadFactorAdjustment(Type type) {
|
||||
return new ImplementationType( type, true, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link ImplementationType} that has the same {@link #initialCapacityConstructor} and
|
||||
* {@link #loadFactorAdjustment}, but a different underlying {@link Type}
|
||||
*
|
||||
* @param type to be replaced
|
||||
*
|
||||
* @return a new implementation type with the given {@code type}
|
||||
*/
|
||||
public ImplementationType createNew(Type type) {
|
||||
return new ImplementationType( type, initialCapacityConstructor, loadFactorAdjustment );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the underlying {@link Type}
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the underlying type has a constructor for {@link int} {@code initialCapacity}, {@code
|
||||
* false} otherwise
|
||||
*/
|
||||
public boolean hasInitialCapacityConstructor() {
|
||||
return initialCapacityConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this method returns {@code true} then {@link #hasInitialCapacityConstructor()} also returns {@code true}
|
||||
*
|
||||
* @return {@code true} if the underlying type needs adjustment for the initial capacity constructor, {@code
|
||||
* false} otherwise
|
||||
*/
|
||||
public boolean isLoadFactorAdjustment() {
|
||||
return loadFactorAdjustment;
|
||||
}
|
||||
}
|
@ -70,7 +70,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
private final TypeElement typeElement;
|
||||
private final List<Type> typeParameters;
|
||||
|
||||
private final Type implementationType;
|
||||
private final ImplementationType implementationType;
|
||||
private final Type componentType;
|
||||
|
||||
private final String packageName;
|
||||
@ -103,7 +103,7 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
//CHECKSTYLE:OFF
|
||||
public Type(Types typeUtils, Elements elementUtils, TypeFactory typeFactory,
|
||||
TypeMirror typeMirror, TypeElement typeElement,
|
||||
List<Type> typeParameters, Type implementationType, Type componentType,
|
||||
List<Type> typeParameters, ImplementationType implementationType, Type componentType,
|
||||
String packageName, String name, String qualifiedName,
|
||||
boolean isInterface, boolean isEnumType, boolean isIterableType,
|
||||
boolean isCollectionType, boolean isMapType, boolean isStreamType, boolean isImported) {
|
||||
@ -209,6 +209,10 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
* type, {@code null} otherwise.
|
||||
*/
|
||||
public Type getImplementationType() {
|
||||
return implementationType != null ? implementationType.getType() : null;
|
||||
}
|
||||
|
||||
public ImplementationType getImplementation() {
|
||||
return implementationType;
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,10 @@ import org.mapstruct.ap.internal.util.TypeHierarchyErroneousException;
|
||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withDefaultConstructor;
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withInitialCapacity;
|
||||
import static org.mapstruct.ap.internal.model.common.ImplementationType.withLoadFactorAdjustment;
|
||||
|
||||
/**
|
||||
* Factory creating {@link Type} instances.
|
||||
*
|
||||
@ -77,7 +81,7 @@ public class TypeFactory {
|
||||
private final TypeMirror mapType;
|
||||
private final TypeMirror streamType;
|
||||
|
||||
private final Map<String, Type> implementationTypes = new HashMap<String, Type>();
|
||||
private final Map<String, ImplementationType> implementationTypes = new HashMap<String, ImplementationType>();
|
||||
private final Map<String, String> importedQualifiedTypesBySimpleName = new HashMap<String, String>();
|
||||
|
||||
public TypeFactory(Elements elementUtils, Types typeUtils, RoundContext roundContext) {
|
||||
@ -92,19 +96,25 @@ public class TypeFactory {
|
||||
TypeElement streamTypeElement = elementUtils.getTypeElement( JavaStreamConstants.STREAM_FQN );
|
||||
streamType = streamTypeElement == null ? null : typeUtils.erasure( streamTypeElement.asType() );
|
||||
|
||||
implementationTypes.put( Iterable.class.getName(), getType( ArrayList.class ) );
|
||||
implementationTypes.put( Collection.class.getName(), getType( ArrayList.class ) );
|
||||
implementationTypes.put( List.class.getName(), getType( ArrayList.class ) );
|
||||
implementationTypes.put( Iterable.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) );
|
||||
implementationTypes.put( Collection.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) );
|
||||
implementationTypes.put( List.class.getName(), withInitialCapacity( getType( ArrayList.class ) ) );
|
||||
|
||||
implementationTypes.put( Set.class.getName(), getType( HashSet.class ) );
|
||||
implementationTypes.put( SortedSet.class.getName(), getType( TreeSet.class ) );
|
||||
implementationTypes.put( NavigableSet.class.getName(), getType( TreeSet.class ) );
|
||||
implementationTypes.put( Set.class.getName(), withLoadFactorAdjustment( getType( HashSet.class ) ) );
|
||||
implementationTypes.put( SortedSet.class.getName(), withDefaultConstructor( getType( TreeSet.class ) ) );
|
||||
implementationTypes.put( NavigableSet.class.getName(), withDefaultConstructor( getType( TreeSet.class ) ) );
|
||||
|
||||
implementationTypes.put( Map.class.getName(), getType( HashMap.class ) );
|
||||
implementationTypes.put( SortedMap.class.getName(), getType( TreeMap.class ) );
|
||||
implementationTypes.put( NavigableMap.class.getName(), getType( TreeMap.class ) );
|
||||
implementationTypes.put( ConcurrentMap.class.getName(), getType( ConcurrentHashMap.class ) );
|
||||
implementationTypes.put( ConcurrentNavigableMap.class.getName(), getType( ConcurrentSkipListMap.class ) );
|
||||
implementationTypes.put( Map.class.getName(), withLoadFactorAdjustment( getType( HashMap.class ) ) );
|
||||
implementationTypes.put( SortedMap.class.getName(), withDefaultConstructor( getType( TreeMap.class ) ) );
|
||||
implementationTypes.put( NavigableMap.class.getName(), withDefaultConstructor( getType( TreeMap.class ) ) );
|
||||
implementationTypes.put(
|
||||
ConcurrentMap.class.getName(),
|
||||
withLoadFactorAdjustment( getType( ConcurrentHashMap.class ) )
|
||||
);
|
||||
implementationTypes.put(
|
||||
ConcurrentNavigableMap.class.getName(),
|
||||
withDefaultConstructor( getType( ConcurrentSkipListMap.class ) )
|
||||
);
|
||||
}
|
||||
|
||||
public Type getType(Class<?> type) {
|
||||
@ -151,7 +161,7 @@ public class TypeFactory {
|
||||
throw new TypeHierarchyErroneousException( mirror );
|
||||
}
|
||||
|
||||
Type implementationType = getImplementationType( mirror );
|
||||
ImplementationType implementationType = getImplementationType( mirror );
|
||||
|
||||
boolean isIterableType = typeUtils.isSubtype( mirror, iterableType );
|
||||
boolean isCollectionType = typeUtils.isSubtype( mirror, collectionType );
|
||||
@ -397,20 +407,21 @@ public class TypeFactory {
|
||||
typeUtils.getPrimitiveType( TypeKind.VOID );
|
||||
}
|
||||
|
||||
private Type getImplementationType(TypeMirror mirror) {
|
||||
private ImplementationType getImplementationType(TypeMirror mirror) {
|
||||
if ( mirror.getKind() != TypeKind.DECLARED ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DeclaredType declaredType = (DeclaredType) mirror;
|
||||
|
||||
Type implementationType = implementationTypes.get(
|
||||
ImplementationType implementation = implementationTypes.get(
|
||||
( (TypeElement) declaredType.asElement() ).getQualifiedName()
|
||||
.toString()
|
||||
);
|
||||
|
||||
if ( implementationType != null ) {
|
||||
return new Type(
|
||||
if ( implementation != null ) {
|
||||
Type implementationType = implementation.getType();
|
||||
Type replacement = new Type(
|
||||
typeUtils,
|
||||
elementUtils,
|
||||
this,
|
||||
@ -433,6 +444,7 @@ public class TypeFactory {
|
||||
implementationType.isStreamType(),
|
||||
isImported( implementationType.getName(), implementationType.getFullyQualifiedName() )
|
||||
);
|
||||
return implementation.createNew( replacement );
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -0,0 +1,50 @@
|
||||
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.IterableCreation" -->
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<@compress single_line=true>
|
||||
<#if factoryMethod??>
|
||||
<@includeModel object=factoryMethod targetType=resultType/>
|
||||
<#else>
|
||||
new
|
||||
<#if resultType.implementationType??>
|
||||
<@includeModel object=resultType.implementationType/><#if ext.useSizeIfPossible?? && ext.useSizeIfPossible && canUseSize>( <@sizeForCreation /> )<#else>()</#if>
|
||||
<#else>
|
||||
<@includeModel object=resultType/>()</#if>
|
||||
</#if>
|
||||
</@compress>
|
||||
<#macro sizeForCreation>
|
||||
<@compress single_line=true>
|
||||
<#if loadFactorAdjustment>
|
||||
Math.max( (int) ( <@iterableSize/> / .75f ) + 1, 16 )
|
||||
<#else>
|
||||
<@iterableSize/>
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
<#macro iterableSize>
|
||||
<@compress single_line=true>
|
||||
<#if sourceParameter.type.arrayType>
|
||||
${sourceParameter.name}.length
|
||||
<#else>
|
||||
${sourceParameter.name}.size()
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
@ -47,7 +47,7 @@
|
||||
${resultName}.clear();
|
||||
return<#if returnType.name != "void"> ${resultName}</#if>;
|
||||
<#else>
|
||||
return <@iterableCreation/>;
|
||||
return <@includeModel object=iterableCreation useSizeIfPossible=false/>;
|
||||
</#if>
|
||||
</#if>
|
||||
</#if>
|
||||
@ -63,7 +63,7 @@
|
||||
${resultName}.clear();
|
||||
<#else>
|
||||
<#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side -->
|
||||
<@iterableLocalVarDef/> ${resultName} = <@iterableCreation/>;
|
||||
<@iterableLocalVarDef/> ${resultName} = <@includeModel object=iterableCreation useSizeIfPossible=true/>;
|
||||
</#if>
|
||||
</#if>
|
||||
<#list beforeMappingReferencesWithMappingTarget as callback>
|
||||
@ -125,16 +125,3 @@
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
<#macro iterableCreation>
|
||||
<@compress single_line=true>
|
||||
<#if factoryMethod??>
|
||||
<@includeModel object=factoryMethod targetType=resultType/>
|
||||
<#else>
|
||||
new
|
||||
<#if resultType.implementationType??>
|
||||
<@includeModel object=resultType.implementationType/>
|
||||
<#else>
|
||||
<@includeModel object=resultType/></#if>()
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
|
@ -35,7 +35,7 @@
|
||||
${resultName}.clear();
|
||||
return<#if returnType.name != "void"> ${resultName}</#if>;
|
||||
<#else>
|
||||
return <@returnObjectCreation/>;
|
||||
return <@includeModel object=iterableCreation useSizeIfPossible=false/>;
|
||||
</#if>
|
||||
</#if>
|
||||
}
|
||||
@ -43,7 +43,7 @@
|
||||
<#if existingInstanceMapping>
|
||||
${resultName}.clear();
|
||||
<#else>
|
||||
<@includeModel object=resultType /> ${resultName} = <@returnObjectCreation/>;
|
||||
<@includeModel object=resultType /> ${resultName} = <@includeModel object=iterableCreation useSizeIfPossible=true/>;
|
||||
</#if>
|
||||
|
||||
<#list beforeMappingReferencesWithMappingTarget as callback>
|
||||
@ -83,16 +83,3 @@
|
||||
</#list>
|
||||
</@compress>
|
||||
</#macro>
|
||||
<#macro returnObjectCreation>
|
||||
<@compress single_line=true>
|
||||
<#if factoryMethod??>
|
||||
<@includeModel object=factoryMethod targetType=resultType/>
|
||||
<#else>
|
||||
new
|
||||
<#if resultType.implementationType??>
|
||||
<@includeModel object=resultType.implementationType />
|
||||
<#else>
|
||||
<@includeModel object=resultType /></#if>()
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
|
@ -48,7 +48,7 @@
|
||||
${resultName}.clear();
|
||||
return<#if returnType.name != "void"> ${resultName}</#if>;
|
||||
<#else>
|
||||
return <@iterableCreation/>;
|
||||
return <@includeModel object=iterableCreation useSizeIfPossible=false/>;
|
||||
</#if>
|
||||
<#else>
|
||||
<#if existingInstanceMapping>
|
||||
@ -76,7 +76,7 @@
|
||||
<#elseif needVarDefine>
|
||||
<#assign needVarDefine = false />
|
||||
<#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side -->
|
||||
<@iterableLocalVarDef/> ${resultName} = <@iterableCreation/>;
|
||||
<@iterableLocalVarDef/> ${resultName} = <@includeModel object=iterableCreation useSizeIfPossible=true/>;
|
||||
</#if>
|
||||
<#else>
|
||||
<#-- Streams are immutable so we can't update them -->
|
||||
@ -177,19 +177,6 @@
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
<#macro iterableCreation>
|
||||
<@compress single_line=true>
|
||||
<#if factoryMethod??>
|
||||
<@includeModel object=factoryMethod targetType=resultType/>
|
||||
<#else>
|
||||
new
|
||||
<#if resultType.implementationType??>
|
||||
<@includeModel object=resultType.implementationType/>
|
||||
<#else>
|
||||
<@includeModel object=resultType/></#if>()
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
<#macro iterableCollectionSupplier>
|
||||
<@compress single_line=true>
|
||||
<#if resultType.implementationType??>
|
||||
|
@ -36,11 +36,13 @@ import java.util.SortedSet;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ConcurrentNavigableMap;
|
||||
|
||||
import org.junit.Rule;
|
||||
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;
|
||||
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||
|
||||
@WithClasses({
|
||||
Source.class,
|
||||
@ -52,6 +54,10 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
public class DefaultCollectionImplementationTest {
|
||||
|
||||
@Rule
|
||||
public final GeneratedSource generatedSource = new GeneratedSource()
|
||||
.addComparisonToFixtureFor( SourceTargetMapper.class );
|
||||
|
||||
@Test
|
||||
@IssueKey("6")
|
||||
public void shouldUseDefaultImplementationForConcurrentMap() {
|
||||
|
@ -28,8 +28,8 @@ import org.mapstruct.ap.test.array.source.Scientist;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2016-12-28T17:52:06+0100",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_112 (Oracle Corporation)"
|
||||
date = "2017-05-03T23:47:43+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class ScienceMapperImpl implements ScienceMapper {
|
||||
|
||||
@ -94,7 +94,7 @@ public class ScienceMapperImpl implements ScienceMapper {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ScientistDto> list = new ArrayList<ScientistDto>();
|
||||
List<ScientistDto> list = new ArrayList<ScientistDto>( scientists.length );
|
||||
for ( Scientist scientist : scientists ) {
|
||||
list.add( scientistToDto( scientist ) );
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-04-22T09:19:18+0200",
|
||||
date = "2017-05-06T00:06:20+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class DomainDtoWithNcvsAlwaysMapperImpl implements DomainDtoWithNcvsAlwaysMapper {
|
||||
@ -229,7 +229,7 @@ public class DomainDtoWithNcvsAlwaysMapperImpl implements DomainDtoWithNcvsAlway
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<Long> set = new HashSet<Long>();
|
||||
Set<Long> set = new HashSet<Long>( Math.max( (int) ( list.size() / .75f ) + 1, 16 ) );
|
||||
for ( String string : list ) {
|
||||
set.add( Long.parseLong( string ) );
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-04-09T23:02:48+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_121 (Oracle Corporation)"
|
||||
date = "2017-05-06T00:06:21+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class DomainDtoWithNvmsDefaultMapperImpl implements DomainDtoWithNvmsDefaultMapper {
|
||||
|
||||
@ -254,7 +254,7 @@ public class DomainDtoWithNvmsDefaultMapperImpl implements DomainDtoWithNvmsDefa
|
||||
return new HashSet<Long>();
|
||||
}
|
||||
|
||||
Set<Long> set = new HashSet<Long>();
|
||||
Set<Long> set = new HashSet<Long>( Math.max( (int) ( list.size() / .75f ) + 1, 16 ) );
|
||||
for ( String string : list ) {
|
||||
set.add( Long.parseLong( string ) );
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-04-09T23:02:47+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_121 (Oracle Corporation)"
|
||||
date = "2017-05-06T00:06:20+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class DomainDtoWithNvmsNullMapperImpl implements DomainDtoWithNvmsNullMapper {
|
||||
|
||||
@ -257,7 +257,7 @@ public class DomainDtoWithNvmsNullMapperImpl implements DomainDtoWithNvmsNullMap
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<Long> set = new HashSet<Long>();
|
||||
Set<Long> set = new HashSet<Long>( Math.max( (int) ( list.size() / .75f ) + 1, 16 ) );
|
||||
for ( String string : list ) {
|
||||
set.add( Long.parseLong( string ) );
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-04-22T09:19:17+0200",
|
||||
date = "2017-05-06T00:06:21+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class DomainDtoWithPresenceCheckMapperImpl implements DomainDtoWithPresenceCheckMapper {
|
||||
@ -219,7 +219,7 @@ public class DomainDtoWithPresenceCheckMapperImpl implements DomainDtoWithPresen
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<Long> set = new HashSet<Long>();
|
||||
Set<Long> set = new HashSet<Long>( Math.max( (int) ( list.size() / .75f ) + 1, 16 ) );
|
||||
for ( String string : list ) {
|
||||
set.add( Long.parseLong( string ) );
|
||||
}
|
||||
|
@ -0,0 +1,272 @@
|
||||
/**
|
||||
* 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.collection.defaultimplementation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ConcurrentNavigableMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-05-06T00:20:29+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class SourceTargetMapperImpl implements SourceTargetMapper {
|
||||
|
||||
@Override
|
||||
public Target sourceToTarget(Source source) {
|
||||
if ( source == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Target target = new Target();
|
||||
|
||||
if ( target.getFooListNoSetter() != null ) {
|
||||
List<TargetFoo> list = sourceFoosToTargetFoos( source.getFooList() );
|
||||
if ( list != null ) {
|
||||
target.getFooListNoSetter().addAll( list );
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetFoo sourceFooToTargetFoo(SourceFoo sourceFoo) {
|
||||
if ( sourceFoo == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TargetFoo targetFoo = new TargetFoo();
|
||||
|
||||
targetFoo.setName( sourceFoo.getName() );
|
||||
|
||||
return targetFoo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TargetFoo> sourceFoosToTargetFoos(List<SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<TargetFoo> list = new ArrayList<TargetFoo>( foos.size() );
|
||||
for ( SourceFoo sourceFoo : foos ) {
|
||||
list.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TargetFoo> sourceFoosToTargetFoos(Set<SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<TargetFoo> set = new HashSet<TargetFoo>( Math.max( (int) ( foos.size() / .75f ) + 1, 16 ) );
|
||||
for ( SourceFoo sourceFoo : foos ) {
|
||||
set.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TargetFoo> sourceFoosToTargetFoos(Collection<SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<TargetFoo> collection = new ArrayList<TargetFoo>( foos.size() );
|
||||
for ( SourceFoo sourceFoo : foos ) {
|
||||
collection.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<TargetFoo> sourceFoosToTargetFoos(Iterable<SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<TargetFoo> iterable = new ArrayList<TargetFoo>();
|
||||
for ( SourceFoo sourceFoo : foos ) {
|
||||
iterable.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return iterable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sourceFoosToTargetFoosUsingTargetParameter(List<TargetFoo> targetFoos, Iterable<SourceFoo> sourceFoos) {
|
||||
if ( sourceFoos == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
targetFoos.clear();
|
||||
for ( SourceFoo sourceFoo : sourceFoos ) {
|
||||
targetFoos.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<TargetFoo> sourceFoosToTargetFoosUsingTargetParameterAndReturn(Iterable<SourceFoo> sourceFoos, List<TargetFoo> targetFoos) {
|
||||
if ( sourceFoos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
targetFoos.clear();
|
||||
for ( SourceFoo sourceFoo : sourceFoos ) {
|
||||
targetFoos.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return targetFoos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedSet<TargetFoo> sourceFoosToTargetFooSortedSet(Collection<SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SortedSet<TargetFoo> sortedSet = new TreeSet<TargetFoo>();
|
||||
for ( SourceFoo sourceFoo : foos ) {
|
||||
sortedSet.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return sortedSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableSet<TargetFoo> sourceFoosToTargetFooNavigableSet(Collection<SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NavigableSet<TargetFoo> navigableSet = new TreeSet<TargetFoo>();
|
||||
for ( SourceFoo sourceFoo : foos ) {
|
||||
navigableSet.add( sourceFooToTargetFoo( sourceFoo ) );
|
||||
}
|
||||
|
||||
return navigableSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TargetFoo> sourceFooMapToTargetFooMap(Map<Long, SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, TargetFoo> map = new HashMap<String, TargetFoo>( Math.max( (int) ( foos.size() / .75f ) + 1, 16 ) );
|
||||
|
||||
for ( java.util.Map.Entry<Long, SourceFoo> entry : foos.entrySet() ) {
|
||||
String key = String.valueOf( entry.getKey() );
|
||||
TargetFoo value = sourceFooToTargetFoo( entry.getValue() );
|
||||
map.put( key, value );
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedMap<String, TargetFoo> sourceFooMapToTargetFooSortedMap(Map<Long, SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SortedMap<String, TargetFoo> sortedMap = new TreeMap<String, TargetFoo>();
|
||||
|
||||
for ( java.util.Map.Entry<Long, SourceFoo> entry : foos.entrySet() ) {
|
||||
String key = String.valueOf( entry.getKey() );
|
||||
TargetFoo value = sourceFooToTargetFoo( entry.getValue() );
|
||||
sortedMap.put( key, value );
|
||||
}
|
||||
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableMap<String, TargetFoo> sourceFooMapToTargetFooNavigableMap(Map<Long, SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NavigableMap<String, TargetFoo> navigableMap = new TreeMap<String, TargetFoo>();
|
||||
|
||||
for ( java.util.Map.Entry<Long, SourceFoo> entry : foos.entrySet() ) {
|
||||
String key = String.valueOf( entry.getKey() );
|
||||
TargetFoo value = sourceFooToTargetFoo( entry.getValue() );
|
||||
navigableMap.put( key, value );
|
||||
}
|
||||
|
||||
return navigableMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConcurrentMap<String, TargetFoo> sourceFooMapToTargetFooConcurrentMap(Map<Long, SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ConcurrentMap<String, TargetFoo> concurrentMap = new ConcurrentHashMap<String, TargetFoo>( Math.max( (int) ( foos.size() / .75f ) + 1, 16 ) );
|
||||
|
||||
for ( java.util.Map.Entry<Long, SourceFoo> entry : foos.entrySet() ) {
|
||||
String key = String.valueOf( entry.getKey() );
|
||||
TargetFoo value = sourceFooToTargetFoo( entry.getValue() );
|
||||
concurrentMap.put( key, value );
|
||||
}
|
||||
|
||||
return concurrentMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConcurrentNavigableMap<String, TargetFoo> sourceFooMapToTargetFooConcurrentNavigableMap(Map<Long, SourceFoo> foos) {
|
||||
if ( foos == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ConcurrentNavigableMap<String, TargetFoo> concurrentNavigableMap = new ConcurrentSkipListMap<String, TargetFoo>();
|
||||
|
||||
for ( java.util.Map.Entry<Long, SourceFoo> entry : foos.entrySet() ) {
|
||||
String key = String.valueOf( entry.getKey() );
|
||||
TargetFoo value = sourceFooToTargetFoo( entry.getValue() );
|
||||
concurrentNavigableMap.put( key, value );
|
||||
}
|
||||
|
||||
return concurrentNavigableMap;
|
||||
}
|
||||
}
|
@ -24,8 +24,8 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-04-09T23:25:54+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_121 (Oracle Corporation)"
|
||||
date = "2017-05-04T00:00:46+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class UserDtoMapperClassicImpl implements UserDtoMapperClassic {
|
||||
|
||||
@ -95,7 +95,7 @@ public class UserDtoMapperClassicImpl implements UserDtoMapperClassic {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<WheelDto> list = new ArrayList<WheelDto>();
|
||||
List<WheelDto> list = new ArrayList<WheelDto>( wheels.size() );
|
||||
for ( Wheel wheel : wheels ) {
|
||||
list.add( mapWheel( wheel ) );
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-04-09T23:25:54+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_121 (Oracle Corporation)"
|
||||
date = "2017-05-04T00:00:47+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class UserDtoMapperSmartImpl implements UserDtoMapperSmart {
|
||||
|
||||
@ -78,7 +78,7 @@ public class UserDtoMapperSmartImpl implements UserDtoMapperSmart {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<WheelDto> list1 = new ArrayList<WheelDto>();
|
||||
List<WheelDto> list1 = new ArrayList<WheelDto>( list.size() );
|
||||
for ( Wheel wheel : list ) {
|
||||
list1.add( wheelToWheelDto( wheel ) );
|
||||
}
|
||||
@ -165,7 +165,7 @@ public class UserDtoMapperSmartImpl implements UserDtoMapperSmart {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<org.mapstruct.ap.test.nestedbeans.other.WheelDto> list1 = new ArrayList<org.mapstruct.ap.test.nestedbeans.other.WheelDto>();
|
||||
List<org.mapstruct.ap.test.nestedbeans.other.WheelDto> list1 = new ArrayList<org.mapstruct.ap.test.nestedbeans.other.WheelDto>( list.size() );
|
||||
for ( Wheel wheel : list ) {
|
||||
list1.add( wheelToWheelDto1( wheel ) );
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-03-01T22:15:22+0100",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_112 (Oracle Corporation)"
|
||||
date = "2017-05-04T00:00:45+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class UserDtoUpdateMapperSmartImpl implements UserDtoUpdateMapperSmart {
|
||||
|
||||
@ -85,7 +85,7 @@ public class UserDtoUpdateMapperSmartImpl implements UserDtoUpdateMapperSmart {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<WheelDto> list1 = new ArrayList<WheelDto>();
|
||||
List<WheelDto> list1 = new ArrayList<WheelDto>( list.size() );
|
||||
for ( Wheel wheel : list ) {
|
||||
list1.add( wheelToWheelDto( wheel ) );
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ import javax.annotation.Generated;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
||||
date = "2017-03-13T22:32:15+0100",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_121 (Oracle Corporation)"
|
||||
date = "2017-05-06T00:11:06+0200",
|
||||
comments = "version: , compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
|
||||
)
|
||||
public class CompanyMapper1Impl implements CompanyMapper1 {
|
||||
|
||||
@ -96,7 +96,7 @@ public class CompanyMapper1Impl implements CompanyMapper1 {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<SecretaryEntity, EmployeeEntity> map1 = new HashMap<SecretaryEntity, EmployeeEntity>();
|
||||
Map<SecretaryEntity, EmployeeEntity> map1 = new HashMap<SecretaryEntity, EmployeeEntity>( Math.max( (int) ( map.size() / .75f ) + 1, 16 ) );
|
||||
|
||||
for ( java.util.Map.Entry<SecretaryDto, EmployeeDto> entry : map.entrySet() ) {
|
||||
SecretaryEntity key = secretaryDtoToSecretaryEntity( entry.getKey() );
|
||||
|
Loading…
x
Reference in New Issue
Block a user