mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#679 Adding testcases, helpermethods for decimalconversion, doc update
This commit is contained in:
parent
607d0fd6f0
commit
3700052cc6
@ -4,6 +4,7 @@
|
||||
Andreas Gudian
|
||||
Christian Schuster
|
||||
Christophe Labouisse
|
||||
Ciaran Liedeman
|
||||
Dilip Krishnan
|
||||
Ewald Volkert
|
||||
Gunnar Morling
|
||||
|
@ -24,6 +24,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -47,10 +48,10 @@ public @interface IterableMapping {
|
||||
String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* A format string as processable by {@link java.text.DecimalFormat} if the annotated method maps from a
|
||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
||||
*
|
||||
* @return A decimal format string as processable by {@link java.text.DecimalFormat}.
|
||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||
*/
|
||||
String numberFormat() default "";
|
||||
|
||||
|
@ -24,6 +24,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -54,6 +55,22 @@ public @interface MapMapping {
|
||||
*/
|
||||
String valueDateFormat() default "";
|
||||
|
||||
/**
|
||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other key types.
|
||||
*
|
||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||
*/
|
||||
String keyNumberFormat() default "";
|
||||
|
||||
/**
|
||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other value types.
|
||||
*
|
||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||
*/
|
||||
String valueNumberFormat() default "";
|
||||
|
||||
/**
|
||||
* A key value qualifier can be specified to aid the selection process of a suitable mapper. This is useful in
|
||||
* case multiple mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found'
|
||||
|
@ -25,6 +25,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -85,10 +86,10 @@ public @interface Mapping {
|
||||
String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* A format string as processable by {@link java.text.DecimalFormat} if the annotated method maps from a
|
||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
||||
*
|
||||
* @return A decimal format string as processable by {@link java.text.DecimalFormat}.
|
||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||
*/
|
||||
String numberFormat() default "";
|
||||
|
||||
|
@ -24,6 +24,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -83,10 +84,10 @@ public @interface Mapping {
|
||||
String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* A format string as processable by {@link java.text.DecimalFormat} if the annotated method maps from a
|
||||
* A format string as processable by {@link DecimalFormat} if the annotated method maps from a
|
||||
* {@link Number} to a {@link String} or vice-versa. Will be ignored for all other element types.
|
||||
*
|
||||
* @return A decimal format string as processable by {@link java.text.DecimalFormat}.
|
||||
* @return A decimal format string as processable by {@link DecimalFormat}.
|
||||
*/
|
||||
String numberFormat() default "";
|
||||
|
||||
|
@ -505,11 +505,42 @@ Currently the following conversions are applied automatically:
|
||||
Converting from larger data types to smaller ones (e.g. from `long` to `int`) can cause a value or precision loss. There https://github.com/mapstruct/mapstruct/issues/5[will be] an option for raising a warning in such cases in a future MapStruct version.
|
||||
====
|
||||
|
||||
* Between all Java primitive types (including their wrappers) and `String`, e.g. between `int` and `String` or `Boolean` and `String`.
|
||||
* Between all Java primitive types (including their wrappers) and `String`, e.g. between `int` and `String` or `Boolean` and `String`. A format string as understood by `java.text.DecimalFormat` can be specified.
|
||||
|
||||
.Conversion from int to String
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
@Mapper
|
||||
public interface CarMapper {
|
||||
|
||||
@Mapping(source = "price", numberFormat = "$#.00")
|
||||
CarDto carToCarDto(Car car);
|
||||
|
||||
@IterableMapping(numberFormat = "$#.00")
|
||||
List<String> prices(List<Integer> prices);
|
||||
}
|
||||
----
|
||||
====
|
||||
* Between `enum` types and `String`.
|
||||
|
||||
* Between big number types (`java.math.BigInteger`, `java.math.BigDecimal`) and Java primitive types (including their wrappers) as well as String
|
||||
* Between big number types (`java.math.BigInteger`, `java.math.BigDecimal`) and Java primitive types (including their wrappers) as well as String. A format string as understood by `java.text.DecimalFormat` can be specified.
|
||||
.Conversion from BigDecimal to String
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
@Mapper
|
||||
public interface CarMapper {
|
||||
|
||||
@Mapping(source = "power", numberFormat = "#.##E0")
|
||||
CarDto carToCarDto(Car car);
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
* Between `JAXBElement<T>` and `T`, `List<JAXBElement<T>>` and `List<T>`
|
||||
|
||||
|
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright 2012-2016 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.conversion;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link PrimitiveToStringConversion}, {@link WrapperToStringConversion},
|
||||
* {@link BigDecimalToStringConversion} and {@link BigIntegerToStringConversion}
|
||||
*
|
||||
* Contains shared utility methods.
|
||||
*
|
||||
* @author Ciaran Liedeman
|
||||
*/
|
||||
public abstract class AbstractNumberToStringConversion extends SimpleConversion {
|
||||
|
||||
private final boolean sourceTypeNumberSubclass;
|
||||
|
||||
public AbstractNumberToStringConversion(boolean sourceTypeNumberSubclass) {
|
||||
|
||||
this.sourceTypeNumberSubclass = sourceTypeNumberSubclass;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<Type> getToConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
else {
|
||||
return super.getToConversionImportTypes( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean requiresDecimalFormat(ConversionContext conversionContext) {
|
||||
return sourceTypeNumberSubclass && conversionContext.getNumberFormat() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
else {
|
||||
return super.getFromConversionImportTypes( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Type> getFromConversionExceptionTypes(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
return Collections.singletonList( conversionContext.getTypeFactory().getType( ParseException.class ) );
|
||||
}
|
||||
else {
|
||||
return super.getFromConversionExceptionTypes( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -18,39 +18,76 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between {@link BigDecimal} and {@link String}.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class BigDecimalToStringConversion extends PossibleNumberToStringConversion {
|
||||
public class BigDecimalToStringConversion extends AbstractNumberToStringConversion {
|
||||
|
||||
public BigDecimalToStringConversion() {
|
||||
super( BigDecimal.class );
|
||||
super( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackToExpression(ConversionContext conversionContext) {
|
||||
public String getToExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".format( <SOURCE> )" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "<SOURCE>.toString()";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackFromExpression(ConversionContext conversionContext) {
|
||||
public String getFromExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( "(BigDecimal) " );
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".parse( <SOURCE> )" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "new BigDecimal( <SOURCE> )";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
Set<Type> importTypes = new HashSet<Type>();
|
||||
importTypes.addAll( super.getFromConversionImportTypes( conversionContext ) );
|
||||
importTypes.add( conversionContext.getTypeFactory().getType( BigDecimal.class ) );
|
||||
return importTypes;
|
||||
return asSet( conversionContext.getTypeFactory().getType( BigDecimal.class ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
HelperMethod helperMethod = new CreateDecimalFormat( conversionContext.getTypeFactory() );
|
||||
return Arrays.asList( helperMethod );
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "createDecimalFormat( " );
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,39 +18,81 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* Conversion between {@link BigInteger} and {@link String}.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class BigIntegerToStringConversion extends PossibleNumberToStringConversion {
|
||||
public class BigIntegerToStringConversion extends AbstractNumberToStringConversion {
|
||||
|
||||
public BigIntegerToStringConversion() {
|
||||
super( BigInteger.class );
|
||||
super( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackToExpression(ConversionContext conversionContext) {
|
||||
public String getToExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".format( <SOURCE> )" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "<SOURCE>.toString()";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackFromExpression(ConversionContext conversionContext) {
|
||||
public String getFromExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( "( (BigDecimal) " );
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".parse( <SOURCE> )" );
|
||||
sb.append( " ).toBigInteger()" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "new BigInteger( <SOURCE> )";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
Set<Type> importTypes = new HashSet<Type>();
|
||||
importTypes.addAll( super.getFromConversionImportTypes( conversionContext ) );
|
||||
importTypes.add( conversionContext.getTypeFactory().getType( BigInteger.class ) );
|
||||
return importTypes;
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
// no imports are required when decimal format is used.
|
||||
return super.getFromConversionImportTypes( conversionContext );
|
||||
}
|
||||
else {
|
||||
return asSet( conversionContext.getTypeFactory().getType( BigInteger.class ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
HelperMethod helperMethod = new CreateDecimalFormat( conversionContext.getTypeFactory() );
|
||||
return Arrays.asList( helperMethod );
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "createDecimalFormat( " );
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,11 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import java.util.List;
|
||||
import org.mapstruct.ap.internal.model.TypeConversion;
|
||||
import org.mapstruct.ap.internal.model.assignment.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
|
||||
/**
|
||||
* Implementations create inline {@link TypeConversion}s such as
|
||||
@ -52,4 +54,11 @@ public interface ConversionProvider {
|
||||
* @return A conversion from target to source.
|
||||
*/
|
||||
Assignment from(ConversionContext conversionContext);
|
||||
|
||||
/**
|
||||
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
||||
*
|
||||
* @return any helper methods when required.
|
||||
*/
|
||||
List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext);
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright 2012-2016 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.conversion;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Set;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import static org.mapstruct.ap.internal.util.Collections.asSet;
|
||||
|
||||
/**
|
||||
* HelperMethod that creates a {@link java.text.DecimalFormat}
|
||||
*
|
||||
* {@code DecimalFormat df = new DecimalFormat( numberFormat )}
|
||||
* with setParseBigDecimal set to true.
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public class CreateDecimalFormat extends HelperMethod {
|
||||
|
||||
|
||||
private final Parameter parameter;
|
||||
private final Type returnType;
|
||||
private final Set<Type> importTypes;
|
||||
|
||||
public CreateDecimalFormat(TypeFactory typeFactory) {
|
||||
this.parameter = new Parameter( "numberFormat", typeFactory.getType( String.class ) );
|
||||
this.returnType = typeFactory.getType( DecimalFormat.class );
|
||||
this.importTypes = asSet( parameter.getType(), returnType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Type> getImportTypes() {
|
||||
return importTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parameter getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
}
|
@ -25,10 +25,12 @@ import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.mapstruct.ap.internal.model.AssignmentFactory;
|
||||
import org.mapstruct.ap.internal.model.assignment.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
/**
|
||||
@ -56,6 +58,11 @@ public class DateToStringConversion implements ConversionProvider {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private String getConversionExpression(ConversionContext conversionContext, String method) {
|
||||
StringBuilder conversionString = new StringBuilder( "new SimpleDateFormat(" );
|
||||
|
||||
|
@ -1,168 +0,0 @@
|
||||
/**
|
||||
* 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.internal.conversion;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
|
||||
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Conversion hooks for {@link Number} to {@link String}. The idea being that <em>if</em>
|
||||
* we have a conversion to string and the source type is a {@code Number} and the mapping
|
||||
* has a {@link org.mapstruct.Mapping#numberFormat()} we will replace the standard conversion
|
||||
* with a {@link DecimalFormat} version
|
||||
*
|
||||
* @author Ciaran Liedeman
|
||||
*/
|
||||
public abstract class PossibleNumberToStringConversion extends SimpleConversion {
|
||||
|
||||
protected final Class<?> primitiveType;
|
||||
protected final Class<?> wrapperType;
|
||||
private final Class<?> sourceType;
|
||||
private boolean sourceTypeNumberSubclass;
|
||||
|
||||
public PossibleNumberToStringConversion(final Class<?> sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
|
||||
if ( sourceType.isPrimitive() ) {
|
||||
wrapperType = NativeTypes.getWrapperType( sourceType );
|
||||
primitiveType = sourceType;
|
||||
}
|
||||
else {
|
||||
wrapperType = sourceType;
|
||||
primitiveType = NativeTypes.getPrimitiveType( sourceType );
|
||||
}
|
||||
|
||||
sourceTypeNumberSubclass = NativeTypes.isNumber( primitiveType )
|
||||
|| NativeTypes.isNumber( sourceType );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getToExpression(ConversionContext conversionContext) {
|
||||
if ( isDecimalFormatConversion( conversionContext ) ) {
|
||||
return getFormatterToConversionExpression( conversionContext );
|
||||
}
|
||||
else {
|
||||
return getFallbackToExpression( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromExpression(ConversionContext conversionContext) {
|
||||
if ( isDecimalFormatConversion( conversionContext ) ) {
|
||||
return getFormatterFromConversionExpression( conversionContext );
|
||||
}
|
||||
else {
|
||||
return getFallbackFromExpression( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getFallbackToExpression(ConversionContext conversionContext);
|
||||
|
||||
protected abstract String getFallbackFromExpression(ConversionContext conversionContext);
|
||||
|
||||
|
||||
public Set<Type> getToConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( isDecimalFormatConversion( conversionContext ) ) {
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
else {
|
||||
return super.getToConversionImportTypes( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDecimalFormatConversion(ConversionContext conversionContext) {
|
||||
return sourceTypeNumberSubclass && conversionContext.getNumberFormat() != null;
|
||||
}
|
||||
|
||||
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
|
||||
if ( isDecimalFormatConversion( conversionContext ) ) {
|
||||
return Collections.singleton( conversionContext.getTypeFactory().getType( DecimalFormat.class ) );
|
||||
}
|
||||
else {
|
||||
return super.getFromConversionImportTypes( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Type> getFromConversionExceptionTypes(ConversionContext conversionContext) {
|
||||
if ( isDecimalFormatConversion( conversionContext ) ) {
|
||||
return Collections.singletonList( conversionContext.getTypeFactory().getType( ParseException.class ) );
|
||||
}
|
||||
else {
|
||||
return super.getFromConversionExceptionTypes( conversionContext );
|
||||
}
|
||||
}
|
||||
|
||||
private String getFormatterToConversionExpression(ConversionContext conversionContext) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".format" );
|
||||
sb.append( "( <SOURCE> )" );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getFormatterFromConversionExpression(ConversionContext conversionContext) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".parse" );
|
||||
sb.append( "( <SOURCE> ).toString()" );
|
||||
|
||||
return getParseTypeExpression( sb.toString() );
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "new DecimalFormat( " );
|
||||
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
|
||||
protected String getParseTypeExpression(String input) {
|
||||
if ( BigDecimal.class == sourceType ) {
|
||||
// TODO this step should be avoided, we return a BigDecimal from the formatter
|
||||
return "new BigDecimal(" + input + ")";
|
||||
}
|
||||
else if ( BigInteger.class == sourceType ) {
|
||||
return "new BigInteger(" + input + ")";
|
||||
}
|
||||
else {
|
||||
return wrapperType.getSimpleName() + ".parse" +
|
||||
Strings.capitalize( primitiveType.getSimpleName() ) + "( " + input + " )";
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
/**
|
||||
* Conversion between primitive types such as {@code byte} or {@code long} and
|
||||
@ -26,23 +28,58 @@ import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class PrimitiveToStringConversion extends PossibleNumberToStringConversion {
|
||||
public class PrimitiveToStringConversion extends AbstractNumberToStringConversion {
|
||||
|
||||
private final Class<?> sourceType;
|
||||
private final Class<?> wrapperType;
|
||||
|
||||
public PrimitiveToStringConversion(Class<?> sourceType) {
|
||||
super( sourceType );
|
||||
super( NativeTypes.isNumber( sourceType ) );
|
||||
if ( !sourceType.isPrimitive() ) {
|
||||
throw new IllegalArgumentException( sourceType + " is no primitive type." );
|
||||
}
|
||||
|
||||
this.sourceType = sourceType;
|
||||
this.wrapperType = NativeTypes.getWrapperType( sourceType );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackToExpression(ConversionContext conversionContext) {
|
||||
public String getToExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".format( <SOURCE> )" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "String.valueOf( <SOURCE> )";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackFromExpression(ConversionContext conversionContext) {
|
||||
return getParseTypeExpression( "<SOURCE>" );
|
||||
public String getFromExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".parse( <SOURCE> )." );
|
||||
sb.append( sourceType.getSimpleName() );
|
||||
sb.append( "Value()" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return wrapperType.getSimpleName() + ".parse"
|
||||
+ Strings.capitalize( sourceType.getSimpleName() ) + "( <SOURCE> )";
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "new DecimalFormat( " );
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,11 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.mapstruct.ap.internal.model.assignment.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
|
||||
/**
|
||||
* A {@link ConversionProvider} which creates the reversed conversions for a
|
||||
@ -48,4 +51,10 @@ public class ReverseConversion implements ConversionProvider {
|
||||
public Assignment from(ConversionContext conversionContext) {
|
||||
return conversionProvider.to( conversionContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.mapstruct.ap.internal.model.AssignmentFactory;
|
||||
import org.mapstruct.ap.internal.model.TypeConversion;
|
||||
import org.mapstruct.ap.internal.model.assignment.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
/**
|
||||
@ -55,6 +56,12 @@ public abstract class SimpleConversion implements ConversionProvider {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HelperMethod> getRequiredHelperMethods(ConversionContext conversionContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the conversion string from source to target. The placeholder {@code <SOURCE>} can be used to represent a
|
||||
* reference to the source value.
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.mapstruct.ap.internal.conversion;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.util.NativeTypes;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
/**
|
||||
@ -26,24 +27,58 @@ import org.mapstruct.ap.internal.util.Strings;
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class WrapperToStringConversion extends PossibleNumberToStringConversion {
|
||||
public class WrapperToStringConversion extends AbstractNumberToStringConversion {
|
||||
|
||||
private final Class<?> sourceType;
|
||||
private final Class<?> primitiveType;
|
||||
|
||||
public WrapperToStringConversion(Class<?> sourceType) {
|
||||
super( sourceType );
|
||||
super( NativeTypes.isNumber( sourceType ) );
|
||||
if ( sourceType.isPrimitive() ) {
|
||||
throw new IllegalArgumentException( sourceType + " is no wrapper type." );
|
||||
}
|
||||
|
||||
this.sourceType = sourceType;
|
||||
this.primitiveType = NativeTypes.getPrimitiveType( sourceType );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackToExpression(ConversionContext conversionContext) {
|
||||
public String getToExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".format( <SOURCE> )" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return "String.valueOf( <SOURCE> )";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFallbackFromExpression(ConversionContext conversionContext) {
|
||||
return sourceType.getSimpleName() + ".parse" +
|
||||
Strings.capitalize( primitiveType.getSimpleName() ) + "( <SOURCE> )";
|
||||
public String getFromExpression(ConversionContext conversionContext) {
|
||||
if ( requiresDecimalFormat( conversionContext ) ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
appendDecimalFormatter( sb, conversionContext );
|
||||
sb.append( ".parse( <SOURCE> )." );
|
||||
sb.append( primitiveType.getSimpleName() );
|
||||
sb.append( "Value()" );
|
||||
return sb.toString();
|
||||
}
|
||||
else {
|
||||
return sourceType.getSimpleName() + ".parse"
|
||||
+ Strings.capitalize( primitiveType.getSimpleName() ) + "( <SOURCE> )";
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDecimalFormatter(StringBuilder sb, ConversionContext conversionContext) {
|
||||
sb.append( "new DecimalFormat( " );
|
||||
if ( conversionContext.getNumberFormat() != null ) {
|
||||
sb.append( "\"" );
|
||||
sb.append( conversionContext.getNumberFormat() );
|
||||
sb.append( "\"" );
|
||||
}
|
||||
|
||||
sb.append( " )" );
|
||||
}
|
||||
}
|
||||
|
@ -293,8 +293,7 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
.targetPropertyName( mapping.getTargetName() )
|
||||
.sourceReference( sourceRef )
|
||||
.selectionParameters( mapping.getSelectionParameters() )
|
||||
.dateFormat( mapping.getDateFormat() )
|
||||
.numberFormat( mapping.getNumberFormat() )
|
||||
.formattingParameters( mapping.getFormattingParameters() )
|
||||
.existingVariableNames( existingVariableNames )
|
||||
.dependsOn( mapping.getDependsOn() )
|
||||
.defaultValue( mapping.getDefaultValue() )
|
||||
@ -318,7 +317,7 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
.targetWriteAccessor( targetWriteAccessor )
|
||||
.targetReadAccessor( getTargetPropertyReadAccessor( mapping.getTargetName() ) )
|
||||
.targetPropertyName( mapping.getTargetName() )
|
||||
.dateFormat( mapping.getDateFormat() )
|
||||
.formattingParameters( mapping.getFormattingParameters() )
|
||||
.selectionParameters( mapping.getSelectionParameters() )
|
||||
.existingVariableNames( existingVariableNames )
|
||||
.dependsOn( mapping.getDependsOn() )
|
||||
@ -415,9 +414,8 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
.targetReadAccessor( getTargetPropertyReadAccessor( targetProperty.getKey() ) )
|
||||
.targetPropertyName( targetProperty.getKey() )
|
||||
.sourceReference( sourceRef )
|
||||
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
||||
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
||||
.dateFormat( mapping != null ? mapping.getDateFormat() : null )
|
||||
.numberFormat( mapping != null ? mapping.getNumberFormat() : null )
|
||||
.defaultValue( mapping != null ? mapping.getDefaultValue() : null )
|
||||
.existingVariableNames( existingVariableNames )
|
||||
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() )
|
||||
@ -480,9 +478,8 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
.targetReadAccessor( getTargetPropertyReadAccessor( targetProperty.getKey() ) )
|
||||
.targetPropertyName( targetProperty.getKey() )
|
||||
.sourceReference( sourceRef )
|
||||
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
||||
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
||||
.dateFormat( mapping != null ? mapping.getDateFormat() : null )
|
||||
.numberFormat( mapping != null ? mapping.getNumberFormat() : null )
|
||||
.existingVariableNames( existingVariableNames )
|
||||
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptyList() )
|
||||
.build();
|
||||
|
@ -0,0 +1,247 @@
|
||||
/**
|
||||
* Copyright 2012-2016 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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import org.mapstruct.ap.internal.model.common.Accessibility;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.util.MapperConfiguration;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
/**
|
||||
* A non mapping method to be generated.
|
||||
*
|
||||
* Can be called from for instance conversions or built-in methods as shared helper method.
|
||||
*
|
||||
* One example of such method is the creation of a decimal formatter
|
||||
* {@link org.mapstruct.ap.internal.conversion.CreateDecimalFormat}, which is used in 2 conversions
|
||||
* (BigInteger to String and BigDecimal to String)
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public abstract class HelperMethod implements Method {
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*
|
||||
* @return default method name is equal to class name of build in method name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return Strings.decapitalize( this.getClass().getSimpleName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the types used by this method for which import statements need to be generated. Defaults to the empty
|
||||
* set. To be overridden by implementations in case they make use of additional types (note that the parameter and
|
||||
* return type don't need to be added).
|
||||
*
|
||||
* @return the types used by this method for which import statements need to be generated
|
||||
*/
|
||||
public Set<Type> getImportTypes() {
|
||||
return Collections.<Type>emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* Default the targetType should be assignable to the returnType and the sourceType to the parameter,
|
||||
* excluding generic type variables. When the implementor sees a need for this, this method can be overridden.
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(List<Type> sourceTypes, Type targetType) {
|
||||
throw new IllegalStateException( "Irrelevant." );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Parameter> getSourceParameters() {
|
||||
return getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* For built-in methods, the declaring mapper is always {@code null} as they will be added as private methods to the
|
||||
* generated mapper.
|
||||
*
|
||||
* @return {@code null}
|
||||
*/
|
||||
@Override
|
||||
public final Type getDeclaringMapper() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Parameter> getParameters() {
|
||||
return Arrays.asList( getParameter() );
|
||||
}
|
||||
|
||||
/**
|
||||
* mapping target parameter mechanism not supported for built-in methods
|
||||
*
|
||||
* @return {@code null}
|
||||
*/
|
||||
@Override
|
||||
public Parameter getMappingTargetParameter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* target type parameter mechanism not supported for built-in methods
|
||||
*
|
||||
* @return {@code null}
|
||||
*/
|
||||
@Override
|
||||
public Parameter getTargetTypeParameter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* the conversion context is used to format an auxiliary parameter in the method call with context specific
|
||||
* information such as a date format.
|
||||
*
|
||||
* @param conversionContext context
|
||||
* @return null if no context parameter should be included "null" if there should be an explicit null call
|
||||
* "'dateFormat'" for instance, to indicate how the build-in method should format the date
|
||||
*/
|
||||
public String getContextParameter(ConversionContext conversionContext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* hashCode based on class
|
||||
*
|
||||
* @return hashCode
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.getClass().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* equals based on class
|
||||
*
|
||||
* @param obj other class
|
||||
*
|
||||
* @return true when classes are the same
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( obj == null ) {
|
||||
return false;
|
||||
}
|
||||
return ( getClass() == obj.getClass() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the Java Generic type variables in the parameter do match the type variables in the build in method same
|
||||
* goes for the returnType.
|
||||
*
|
||||
* @param parameter source
|
||||
* @param returnType target
|
||||
* @return {@code true}, iff the the type variables match
|
||||
*/
|
||||
public boolean doTypeVarsMatch(Type parameter, Type returnType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* There's currently only one parameter foreseen instead of a list of parameter
|
||||
*
|
||||
* @return the parameter
|
||||
*/
|
||||
public abstract Parameter getParameter();
|
||||
|
||||
@Override
|
||||
public Accessibility getAccessibility() {
|
||||
return Accessibility.PRIVATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Type> getThrownTypes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getResultType() {
|
||||
return getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getParameterNames() {
|
||||
List<String> parameterNames = new ArrayList<String>( getParameters().size() );
|
||||
for ( Parameter parameter : getParameters() ) {
|
||||
parameterNames.add( parameter.getName() );
|
||||
}
|
||||
|
||||
return parameterNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overridesMethod() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutableElement getExecutable() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getDefiningType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperConfiguration getMapperConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLifecycleCallbackMethod() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdateMethod() {
|
||||
return false; // irrelevant
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ import org.mapstruct.ap.internal.model.assignment.SetterWrapper;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.ForgedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||
@ -55,8 +56,8 @@ public class IterableMappingMethod extends MappingMethod {
|
||||
|
||||
private Method method;
|
||||
private MappingBuilderContext ctx;
|
||||
private String dateFormat;
|
||||
private SelectionParameters selectionParameters;
|
||||
private FormattingParameters formattingParameters;
|
||||
private NullValueMappingStrategyPrism nullValueMappingStrategy;
|
||||
|
||||
public Builder mappingContext(MappingBuilderContext mappingContext) {
|
||||
@ -69,8 +70,8 @@ public class IterableMappingMethod extends MappingMethod {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder dateFormat(String dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
public Builder formattingParameters(FormattingParameters formattingParameters) {
|
||||
this.formattingParameters = formattingParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -104,7 +105,7 @@ public class IterableMappingMethod extends MappingMethod {
|
||||
sourceElementType,
|
||||
targetElementType,
|
||||
null, // there is no targetPropertyName
|
||||
dateFormat,
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
loopVariableName,
|
||||
false
|
||||
|
@ -28,6 +28,7 @@ import org.mapstruct.ap.internal.model.assignment.LocalVarWrapper;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.ForgedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||
@ -50,9 +51,8 @@ public class MapMappingMethod extends MappingMethod {
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private String keyDateFormat;
|
||||
private String keyNumberFormat;
|
||||
private String valueDateFormat;
|
||||
private FormattingParameters keyFormattingParameters;
|
||||
private FormattingParameters valueFormattingParameters;
|
||||
private Method method;
|
||||
private MappingBuilderContext ctx;
|
||||
private NullValueMappingStrategyPrism nullValueMappingStrategy;
|
||||
@ -79,13 +79,13 @@ public class MapMappingMethod extends MappingMethod {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder keyDateFormat(String keyDateFormat) {
|
||||
this.keyDateFormat = keyDateFormat;
|
||||
public Builder keyFormattingParameters(FormattingParameters keyFormattingParameters) {
|
||||
this.keyFormattingParameters = keyFormattingParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder valueDateFormat(String valueDateFormat) {
|
||||
this.valueDateFormat = valueDateFormat;
|
||||
public Builder valueFormattingParameters(FormattingParameters valueFormattingParameters) {
|
||||
this.valueFormattingParameters = valueFormattingParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -94,7 +94,6 @@ public class MapMappingMethod extends MappingMethod {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public MapMappingMethod build() {
|
||||
|
||||
List<Type> sourceTypeParams = first( method.getSourceParameters() ).getType().getTypeParameters();
|
||||
@ -110,7 +109,7 @@ public class MapMappingMethod extends MappingMethod {
|
||||
keySourceType,
|
||||
keyTargetType,
|
||||
null, // there is no targetPropertyName
|
||||
keyDateFormat,
|
||||
keyFormattingParameters,
|
||||
keySelectionParameters,
|
||||
"entry.getKey()",
|
||||
false
|
||||
@ -137,7 +136,7 @@ public class MapMappingMethod extends MappingMethod {
|
||||
valueSourceType,
|
||||
valueTargetType,
|
||||
null, // there is no targetPropertyName
|
||||
valueDateFormat,
|
||||
valueFormattingParameters,
|
||||
valueSelectionParameters,
|
||||
"entry.getValue()",
|
||||
false
|
||||
|
@ -29,6 +29,7 @@ import javax.lang.model.util.Types;
|
||||
import org.mapstruct.ap.internal.model.assignment.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
@ -78,7 +79,7 @@ public class MappingBuilderContext {
|
||||
* @param sourceType parameter to match
|
||||
* @param targetType return type to match
|
||||
* @param targetPropertyName name of the target property
|
||||
* @param dateFormat used for formatting dates in build in methods that need context information
|
||||
* @param formattingParameters used for formatting dates and numbers
|
||||
* @param selectionParameters parameters used in the selection process
|
||||
* @param sourceReference call to source type as string
|
||||
* @param preferUpdateMethods selection should prefer update methods when present.
|
||||
@ -93,7 +94,7 @@ public class MappingBuilderContext {
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
Assignment getTargetAssignment(Method mappingMethod, String mappedElement, Type sourceType, Type targetType,
|
||||
String targetPropertyName, String dateFormat,
|
||||
String targetPropertyName, FormattingParameters formattingParameters,
|
||||
SelectionParameters selectionParameters, String sourceReference,
|
||||
boolean preferUpdateMethods);
|
||||
|
||||
|
@ -47,6 +47,7 @@ import org.mapstruct.ap.internal.model.common.ModelElement;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.ForgedMethod;
|
||||
import org.mapstruct.ap.internal.model.source.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.internal.model.source.SourceReference;
|
||||
@ -166,10 +167,9 @@ public class PropertyMapping extends ModelElement {
|
||||
public static class PropertyMappingBuilder extends MappingBuilderBase<PropertyMappingBuilder> {
|
||||
|
||||
// initial properties
|
||||
private String dateFormat;
|
||||
private String numberFormat;
|
||||
private String defaultValue;
|
||||
private SourceReference sourceReference;
|
||||
private FormattingParameters formattingParameters;
|
||||
private SelectionParameters selectionParameters;
|
||||
|
||||
public PropertyMappingBuilder sourceReference(SourceReference sourceReference) {
|
||||
@ -182,13 +182,8 @@ public class PropertyMapping extends ModelElement {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PropertyMappingBuilder dateFormat(String dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PropertyMappingBuilder numberFormat(String numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
public PropertyMappingBuilder formattingParameters(FormattingParameters formattingParameters) {
|
||||
this.formattingParameters = formattingParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -227,7 +222,7 @@ public class PropertyMapping extends ModelElement {
|
||||
sourceType,
|
||||
targetType,
|
||||
targetPropertyName,
|
||||
dateFormat,
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
sourceRefStr,
|
||||
preferUpdateMethods
|
||||
@ -286,7 +281,7 @@ public class PropertyMapping extends ModelElement {
|
||||
if ( defaultValue != null && !getSourceType().isPrimitive() ) {
|
||||
PropertyMapping build = new ConstantMappingBuilder()
|
||||
.constantExpression( '"' + defaultValue + '"' )
|
||||
.dateFormat( dateFormat )
|
||||
.formattingParameters( formattingParameters )
|
||||
.selectionParameters( selectionParameters )
|
||||
.dependsOn( dependsOn )
|
||||
.existingVariableNames( existingVariableNames )
|
||||
@ -599,7 +594,7 @@ public class PropertyMapping extends ModelElement {
|
||||
public static class ConstantMappingBuilder extends MappingBuilderBase<ConstantMappingBuilder> {
|
||||
|
||||
private String constantExpression;
|
||||
private String dateFormat;
|
||||
private FormattingParameters formattingParameters;
|
||||
private SelectionParameters selectionParameters;
|
||||
|
||||
public ConstantMappingBuilder constantExpression(String constantExpression) {
|
||||
@ -607,8 +602,8 @@ public class PropertyMapping extends ModelElement {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConstantMappingBuilder dateFormat(String dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
public ConstantMappingBuilder formattingParameters(FormattingParameters formattingParameters) {
|
||||
this.formattingParameters = formattingParameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -628,7 +623,7 @@ public class PropertyMapping extends ModelElement {
|
||||
sourceType,
|
||||
targetType,
|
||||
targetPropertyName,
|
||||
dateFormat,
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
constantExpression,
|
||||
method.getMappingTargetParameter() != null
|
||||
|
@ -40,6 +40,12 @@ public class VirtualMappingMethod extends MappingMethod {
|
||||
this.templateName = getTemplateNameForClass( method.getClass() );
|
||||
}
|
||||
|
||||
public VirtualMappingMethod(HelperMethod method) {
|
||||
super( method );
|
||||
this.importTypes = method.getImportTypes();
|
||||
this.templateName = getTemplateNameForClass( method.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright 2012-2016 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.source;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public class FormattingParameters {
|
||||
|
||||
private final String date;
|
||||
private final String number;
|
||||
|
||||
public FormattingParameters(String date, String number) {
|
||||
this.date = date;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
package org.mapstruct.ap.internal.model.source;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
@ -35,11 +34,9 @@ import org.mapstruct.ap.internal.util.Message;
|
||||
*/
|
||||
public class IterableMapping {
|
||||
|
||||
private final String dateFormat;
|
||||
private final SelectionParameters selectionParameters;
|
||||
private final FormattingParameters formattingParameters;
|
||||
private final AnnotationMirror mirror;
|
||||
private final AnnotationValue dateFormatAnnotationValue;
|
||||
private final AnnotationValue numberFormatAnnotationValue;
|
||||
private final NullValueMappingStrategyPrism nullValueMappingStrategy;
|
||||
|
||||
public static IterableMapping fromPrism(IterableMappingPrism iterableMapping, ExecutableElement method,
|
||||
@ -57,6 +54,7 @@ public class IterableMapping {
|
||||
|
||||
if ( !elementTargetTypeIsDefined
|
||||
&& iterableMapping.dateFormat().isEmpty()
|
||||
&& iterableMapping.numberFormat().isEmpty()
|
||||
&& iterableMapping.qualifiedBy().isEmpty()
|
||||
&& iterableMapping.qualifiedByName().isEmpty()
|
||||
&& ( nullValueMappingStrategy == null ) ) {
|
||||
@ -69,50 +67,39 @@ public class IterableMapping {
|
||||
iterableMapping.qualifiedByName(),
|
||||
elementTargetTypeIsDefined ? iterableMapping.elementTargetType() : null );
|
||||
|
||||
return new IterableMapping(iterableMapping.dateFormat(),
|
||||
FormattingParameters formatting = new FormattingParameters(
|
||||
iterableMapping.dateFormat(),
|
||||
iterableMapping.numberFormat() );
|
||||
|
||||
return new IterableMapping( formatting,
|
||||
selection,
|
||||
iterableMapping.mirror,
|
||||
iterableMapping.values.dateFormat(),
|
||||
iterableMapping.values.numberFormat(),
|
||||
nullValueMappingStrategy
|
||||
);
|
||||
}
|
||||
|
||||
private IterableMapping(String dateFormat, SelectionParameters selectionParameters, AnnotationMirror mirror,
|
||||
AnnotationValue dateFormatAnnotationValue, NullValueMappingStrategyPrism nvms) {
|
||||
private IterableMapping(FormattingParameters formattingParameters, SelectionParameters selectionParameters,
|
||||
AnnotationMirror mirror, NullValueMappingStrategyPrism nvms) {
|
||||
|
||||
this.dateFormat = dateFormat;
|
||||
this.formattingParameters = formattingParameters;
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.mirror = mirror;
|
||||
this.dateFormatAnnotationValue = dateFormatAnnotationValue;
|
||||
this.numberFormatAnnotationValue = numberFormatAnnotationValue;
|
||||
this.nullValueMappingStrategy = nvms;
|
||||
}
|
||||
|
||||
public String getDateFormat() {
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
public SelectionParameters getSelectionParameters() {
|
||||
return selectionParameters;
|
||||
}
|
||||
|
||||
public FormattingParameters getFormattingParameters() {
|
||||
return formattingParameters;
|
||||
}
|
||||
|
||||
public AnnotationMirror getMirror() {
|
||||
return mirror;
|
||||
}
|
||||
|
||||
public AnnotationValue getDateFormatAnnotationValue() {
|
||||
return dateFormatAnnotationValue;
|
||||
}
|
||||
|
||||
public String getNumberFormat() {
|
||||
return numberFormat;
|
||||
}
|
||||
|
||||
public AnnotationValue getNumberFormatAnnotationValue() {
|
||||
return numberFormatAnnotationValue;
|
||||
}
|
||||
|
||||
public NullValueMappingStrategyPrism getNullValueMappingStrategy() {
|
||||
return nullValueMappingStrategy;
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ import org.mapstruct.ap.internal.util.Message;
|
||||
*/
|
||||
public class MapMapping {
|
||||
|
||||
private final String keyFormat;
|
||||
private final SelectionParameters keySelectionParameters;
|
||||
private final String valueFormat;
|
||||
private final SelectionParameters valueSelectionParameters;
|
||||
private final FormattingParameters keyFormattingParameters;
|
||||
private final FormattingParameters valueFormattingParameters;
|
||||
private final AnnotationMirror mirror;
|
||||
private final NullValueMappingStrategyPrism nullValueMappingStrategy;
|
||||
|
||||
@ -56,9 +56,11 @@ public class MapMapping {
|
||||
boolean keyTargetTypeIsDefined = !TypeKind.VOID.equals( mapMapping.keyTargetType().getKind() );
|
||||
boolean valueTargetTypeIsDefined = !TypeKind.VOID.equals( mapMapping.valueTargetType().getKind() );
|
||||
if ( mapMapping.keyDateFormat().isEmpty()
|
||||
&& mapMapping.keyNumberFormat().isEmpty()
|
||||
&& mapMapping.keyQualifiedBy().isEmpty()
|
||||
&& mapMapping.keyQualifiedByName().isEmpty()
|
||||
&& mapMapping.valueDateFormat().isEmpty()
|
||||
&& mapMapping.valueNumberFormat().isEmpty()
|
||||
&& mapMapping.valueQualifiedBy().isEmpty()
|
||||
&& mapMapping.valueQualifiedByName().isEmpty()
|
||||
&& !keyTargetTypeIsDefined
|
||||
@ -78,36 +80,45 @@ public class MapMapping {
|
||||
mapMapping.valueQualifiedByName(),
|
||||
valueTargetTypeIsDefined ? mapMapping.valueTargetType() : null);
|
||||
|
||||
return new MapMapping(
|
||||
FormattingParameters keyFormatting = new FormattingParameters(
|
||||
mapMapping.keyDateFormat(),
|
||||
keySelection,
|
||||
mapMapping.keyNumberFormat() );
|
||||
|
||||
FormattingParameters valueFormatting = new FormattingParameters(
|
||||
mapMapping.valueDateFormat(),
|
||||
mapMapping.valueNumberFormat() );
|
||||
|
||||
return new MapMapping(
|
||||
keyFormatting,
|
||||
keySelection,
|
||||
valueFormatting,
|
||||
valueSelection,
|
||||
mapMapping.mirror,
|
||||
nullValueMappingStrategy
|
||||
);
|
||||
}
|
||||
|
||||
private MapMapping(String keyFormat, SelectionParameters keySelectionParameters, String valueFormat,
|
||||
SelectionParameters valueSelectionParameters, AnnotationMirror mirror, NullValueMappingStrategyPrism nvms ) {
|
||||
this.keyFormat = keyFormat;
|
||||
private MapMapping(FormattingParameters keyFormatting, SelectionParameters keySelectionParameters,
|
||||
FormattingParameters valueFormatting, SelectionParameters valueSelectionParameters, AnnotationMirror mirror,
|
||||
NullValueMappingStrategyPrism nvms ) {
|
||||
this.keyFormattingParameters = keyFormatting;
|
||||
this.keySelectionParameters = keySelectionParameters;
|
||||
this.valueFormat = valueFormat;
|
||||
this.valueFormattingParameters = valueFormatting;
|
||||
this.valueSelectionParameters = valueSelectionParameters;
|
||||
this.mirror = mirror;
|
||||
this.nullValueMappingStrategy = nvms;
|
||||
}
|
||||
|
||||
public String getKeyFormat() {
|
||||
return keyFormat;
|
||||
public FormattingParameters getKeyFormattingParameters() {
|
||||
return keyFormattingParameters;
|
||||
}
|
||||
|
||||
public SelectionParameters getKeySelectionParameters() {
|
||||
return keySelectionParameters;
|
||||
}
|
||||
|
||||
public String getValueFormat() {
|
||||
return valueFormat;
|
||||
public FormattingParameters getValueFormattingParameters() {
|
||||
return valueFormattingParameters;
|
||||
}
|
||||
|
||||
public SelectionParameters getValueSelectionParameters() {
|
||||
|
@ -54,9 +54,8 @@ public class Mapping {
|
||||
private final String constant;
|
||||
private final String javaExpression;
|
||||
private final String targetName;
|
||||
private final String dateFormat;
|
||||
private final String numberFormat;
|
||||
private final String defaultValue;
|
||||
private final FormattingParameters formattingParameters;
|
||||
private final SelectionParameters selectionParameters;
|
||||
|
||||
private final boolean isIgnored;
|
||||
@ -145,18 +144,19 @@ public class Mapping {
|
||||
mappingPrism.qualifiedByName(),
|
||||
resultTypeIsDefined ? mappingPrism.resultType() : null);
|
||||
|
||||
FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat );
|
||||
|
||||
return new Mapping(
|
||||
source,
|
||||
constant,
|
||||
expression,
|
||||
mappingPrism.target(),
|
||||
dateFormat,
|
||||
numberFormat,
|
||||
defaultValue,
|
||||
mappingPrism.ignore(),
|
||||
mappingPrism.mirror,
|
||||
mappingPrism.values.source(),
|
||||
mappingPrism.values.target(),
|
||||
formattingParam,
|
||||
selectionParams,
|
||||
mappingPrism.values.dependsOn(),
|
||||
dependsOn
|
||||
@ -165,21 +165,20 @@ public class Mapping {
|
||||
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
private Mapping(String sourceName, String constant, String javaExpression, String targetName,
|
||||
String dateFormat, String defaultValue, boolean isIgnored, AnnotationMirror mirror,
|
||||
String defaultValue, boolean isIgnored, AnnotationMirror mirror,
|
||||
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
||||
SelectionParameters selectionParameters, AnnotationValue dependsOnAnnotationValue,
|
||||
List<String> dependsOn) {
|
||||
FormattingParameters formattingParameters, SelectionParameters selectionParameters,
|
||||
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn) {
|
||||
this.sourceName = sourceName;
|
||||
this.constant = constant;
|
||||
this.javaExpression = javaExpression;
|
||||
this.targetName = targetName;
|
||||
this.dateFormat = dateFormat;
|
||||
this.numberFormat = numberFormat;
|
||||
this.defaultValue = defaultValue;
|
||||
this.isIgnored = isIgnored;
|
||||
this.mirror = mirror;
|
||||
this.sourceAnnotationValue = sourceAnnotationValue;
|
||||
this.targetAnnotationValue = targetAnnotationValue;
|
||||
this.formattingParameters = formattingParameters;
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
|
||||
this.dependsOn = dependsOn;
|
||||
@ -243,18 +242,14 @@ public class Mapping {
|
||||
return targetName;
|
||||
}
|
||||
|
||||
public String getDateFormat() {
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
public String getNumberFormat() {
|
||||
return numberFormat;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public FormattingParameters getFormattingParameters() {
|
||||
return formattingParameters;
|
||||
}
|
||||
|
||||
public SelectionParameters getSelectionParameters() {
|
||||
return selectionParameters;
|
||||
}
|
||||
@ -327,13 +322,12 @@ public class Mapping {
|
||||
null, // constant
|
||||
null, // expression
|
||||
sourceName != null ? sourceName : targetName,
|
||||
dateFormat,
|
||||
numberFormat,
|
||||
null,
|
||||
isIgnored,
|
||||
mirror,
|
||||
sourceAnnotationValue,
|
||||
targetAnnotationValue,
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
dependsOnAnnotationValue,
|
||||
Collections.<String>emptyList()
|
||||
@ -355,13 +349,12 @@ public class Mapping {
|
||||
constant,
|
||||
javaExpression,
|
||||
targetName,
|
||||
dateFormat,
|
||||
numberFormat,
|
||||
defaultValue,
|
||||
isIgnored,
|
||||
mirror,
|
||||
sourceAnnotationValue,
|
||||
targetAnnotationValue,
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
dependsOnAnnotationValue,
|
||||
dependsOn
|
||||
|
@ -50,6 +50,7 @@ import org.mapstruct.ap.internal.model.MappingMethod;
|
||||
import org.mapstruct.ap.internal.model.ValueMappingMethod;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.model.source.MappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
@ -269,12 +270,12 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
|
||||
IterableMappingMethod.Builder builder = new IterableMappingMethod.Builder();
|
||||
|
||||
String dateFormat = null;
|
||||
FormattingParameters formattingParameters = null;
|
||||
SelectionParameters selectionParameters = null;
|
||||
NullValueMappingStrategyPrism nullValueMappingStrategy = null;
|
||||
|
||||
if ( mappingOptions.getIterableMapping() != null ) {
|
||||
dateFormat = mappingOptions.getIterableMapping().getDateFormat();
|
||||
formattingParameters = mappingOptions.getIterableMapping().getFormattingParameters();
|
||||
selectionParameters = mappingOptions.getIterableMapping().getSelectionParameters();
|
||||
nullValueMappingStrategy = mappingOptions.getIterableMapping().getNullValueMappingStrategy();
|
||||
}
|
||||
@ -282,7 +283,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
IterableMappingMethod iterableMappingMethod = builder
|
||||
.mappingContext( mappingContext )
|
||||
.method( method )
|
||||
.dateFormat( dateFormat )
|
||||
.formattingParameters( formattingParameters )
|
||||
.selectionParameters( selectionParameters )
|
||||
.nullValueMappingStrategy( nullValueMappingStrategy )
|
||||
.build();
|
||||
@ -294,26 +295,26 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
|
||||
MapMappingMethod.Builder builder = new MapMappingMethod.Builder();
|
||||
|
||||
String keyDateFormat = null;
|
||||
String valueDateFormat = null;
|
||||
SelectionParameters keySelectionParameters = null;
|
||||
FormattingParameters keyFormattingParameters = null;
|
||||
SelectionParameters valueSelectionParameters = null;
|
||||
FormattingParameters valueFormattingParameters = null;
|
||||
NullValueMappingStrategyPrism nullValueMappingStrategy = null;
|
||||
|
||||
if ( mappingOptions.getMapMapping() != null ) {
|
||||
keyDateFormat = mappingOptions.getMapMapping().getKeyFormat();
|
||||
keySelectionParameters = mappingOptions.getMapMapping().getKeySelectionParameters();
|
||||
keyFormattingParameters = mappingOptions.getMapMapping().getKeyFormattingParameters();
|
||||
valueSelectionParameters = mappingOptions.getMapMapping().getValueSelectionParameters();
|
||||
valueDateFormat = mappingOptions.getMapMapping().getValueFormat();
|
||||
valueFormattingParameters = mappingOptions.getMapMapping().getValueFormattingParameters();
|
||||
nullValueMappingStrategy = mappingOptions.getMapMapping().getNullValueMappingStrategy();
|
||||
}
|
||||
|
||||
MapMappingMethod mapMappingMethod = builder
|
||||
.mappingContext( mappingContext )
|
||||
.method( method )
|
||||
.keyDateFormat( keyDateFormat )
|
||||
.keyFormattingParameters( keyFormattingParameters )
|
||||
.keySelectionParameters( keySelectionParameters )
|
||||
.valueDateFormat( valueDateFormat )
|
||||
.valueFormattingParameters( valueFormattingParameters )
|
||||
.valueSelectionParameters( valueSelectionParameters )
|
||||
.nullValueMappingStrategy( nullValueMappingStrategy )
|
||||
.build();
|
||||
|
@ -43,8 +43,10 @@ import org.mapstruct.ap.internal.model.VirtualMappingMethod;
|
||||
import org.mapstruct.ap.internal.model.assignment.Assignment;
|
||||
import org.mapstruct.ap.internal.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.internal.model.common.DefaultConversionContext;
|
||||
import org.mapstruct.ap.internal.model.HelperMethod;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.FormattingParameters;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
@ -105,12 +107,19 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
@Override
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
public Assignment getTargetAssignment(Method mappingMethod, String mappedElement, Type sourceType,
|
||||
Type targetType, String targetPropertyName, String dateFormat, SelectionParameters selectionParameters,
|
||||
String sourceReference, boolean preferUpdateMapping) {
|
||||
Type targetType, String targetPropertyName, FormattingParameters formattingParameters,
|
||||
SelectionParameters selectionParameters, String sourceReference, boolean preferUpdateMapping) {
|
||||
|
||||
SelectionCriteria criteria =
|
||||
new SelectionCriteria( selectionParameters, targetPropertyName, preferUpdateMapping );
|
||||
|
||||
String dateFormat = null;
|
||||
String numberFormat = null;
|
||||
if ( formattingParameters != null ) {
|
||||
dateFormat = formattingParameters.getDate();
|
||||
numberFormat = formattingParameters.getNumber();
|
||||
}
|
||||
|
||||
ResolvingAttempt attempt = new ResolvingAttempt(
|
||||
sourceModel,
|
||||
mappingMethod,
|
||||
@ -260,9 +269,13 @@ public class MappingResolverImpl implements MappingResolver {
|
||||
if ( conversionProvider == null ) {
|
||||
return null;
|
||||
}
|
||||
ConversionContext ctx = new DefaultConversionContext( typeFactory, messager, sourceType, targetType,
|
||||
dateFormat, numberFormat );
|
||||
|
||||
ConversionContext ctx =
|
||||
new DefaultConversionContext( typeFactory, messager, sourceType, targetType, dateFormat, numberFormat);
|
||||
// add helper methods required in conversion
|
||||
for ( HelperMethod helperMethod : conversionProvider.getRequiredHelperMethods( ctx ) ) {
|
||||
usedVirtualMappings.add( new VirtualMappingMethod( helperMethod ) );
|
||||
}
|
||||
return conversionProvider.to( ctx );
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
<#--
|
||||
|
||||
Copyright 2012-2016 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.
|
||||
|
||||
-->
|
||||
private DecimalFormat ${name}( String numberFormat ) {
|
||||
|
||||
DecimalFormat df = new DecimalFormat( numberFormat );
|
||||
df.setParseBigDecimal( true );
|
||||
return df;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* Copyright 2012-2016 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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* Copyright 2012-2016 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.
|
||||
@ -26,9 +26,14 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.fest.assertions.MapAssert.entry;
|
||||
|
||||
@WithClasses({
|
||||
Source.class,
|
||||
@ -50,6 +55,8 @@ public class NumberFormatConversionTest {
|
||||
source.setIi( 2 );
|
||||
source.setD( 3.0 );
|
||||
source.setDd( 4.0 );
|
||||
source.setF( 3.0f );
|
||||
source.setFf( 4.0f );
|
||||
source.setL( 5L );
|
||||
source.setLl( 6L );
|
||||
source.setB( (byte) 7 );
|
||||
@ -68,6 +75,8 @@ public class NumberFormatConversionTest {
|
||||
assertThat( target.getIi() ).isEqualTo( "2.00" );
|
||||
assertThat( target.getD() ).isEqualTo( "3.00" );
|
||||
assertThat( target.getDd() ).isEqualTo( "4.00" );
|
||||
assertThat( target.getF() ).isEqualTo( "3.00" );
|
||||
assertThat( target.getFf() ).isEqualTo( "4.00" );
|
||||
assertThat( target.getL() ).isEqualTo( "5.00" );
|
||||
assertThat( target.getLl() ).isEqualTo( "6.00" );
|
||||
assertThat( target.getB() ).isEqualTo( "7.00" );
|
||||
@ -87,6 +96,8 @@ public class NumberFormatConversionTest {
|
||||
target.setIi( "2.00" );
|
||||
target.setD( "3.00" );
|
||||
target.setDd( "4.00" );
|
||||
target.setF( "3.00" );
|
||||
target.setFf( "4.00" );
|
||||
target.setL( "5.00" );
|
||||
target.setLl( "6.00" );
|
||||
target.setB( "7.00" );
|
||||
@ -105,6 +116,8 @@ public class NumberFormatConversionTest {
|
||||
assertThat( source.getIi() ).isEqualTo( Integer.valueOf( 2 ) );
|
||||
assertThat( source.getD() ).isEqualTo( 3.0 );
|
||||
assertThat( source.getDd() ).isEqualTo( Double.valueOf( 4.0 ) );
|
||||
assertThat( source.getF() ).isEqualTo( 3.0f );
|
||||
assertThat( source.getFf() ).isEqualTo( Float.valueOf( 4.0f ) );
|
||||
assertThat( source.getL() ).isEqualTo( 5L );
|
||||
assertThat( source.getLl() ).isEqualTo( Long.valueOf( 6L ) );
|
||||
assertThat( source.getB() ).isEqualTo( (byte) 7 );
|
||||
@ -117,4 +130,32 @@ public class NumberFormatConversionTest {
|
||||
assertThat( source.getBigInteger1() ).isEqualTo( new BigInteger( "1234567890000" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldApplyStringConversionsToIterables() {
|
||||
|
||||
List<String> target = SourceTargetMapper.INSTANCE.sourceToTarget( Arrays.asList( 2f ) );
|
||||
|
||||
assertThat( target ).hasSize( 1 );
|
||||
assertThat( target ).isEqualTo( Arrays.asList( "2.00" ) );
|
||||
|
||||
List<Float> source = SourceTargetMapper.INSTANCE.targetToSource( target );
|
||||
assertThat( source ).hasSize( 1 );
|
||||
assertThat( source ).isEqualTo( Arrays.asList( 2.00f ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldApplyStringConversionsToMaps() {
|
||||
|
||||
Map<Float, Float> source1 = new HashMap<Float, Float>();
|
||||
source1.put( 1.0001f, 2.01f );
|
||||
|
||||
Map<String, String> target = SourceTargetMapper.INSTANCE.sourceToTarget( source1 );
|
||||
assertThat( target ).hasSize( 1 );
|
||||
assertThat( target ).includes( entry( "1.00", "2" ) );
|
||||
|
||||
Map<Float, Float> source2 = SourceTargetMapper.INSTANCE.targetToSource( target );
|
||||
assertThat( source2 ).hasSize( 1 );
|
||||
assertThat( source2 ).includes( entry( 1.00f, 2f ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* Copyright 2012-2016 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.
|
||||
@ -27,6 +27,8 @@ public class Source {
|
||||
private Integer ii;
|
||||
private double d;
|
||||
private Double dd;
|
||||
private float f;
|
||||
private Float ff;
|
||||
private long l;
|
||||
private Long ll;
|
||||
private byte b;
|
||||
@ -70,6 +72,22 @@ public class Source {
|
||||
this.dd = dd;
|
||||
}
|
||||
|
||||
public float getF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void setF(float f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public Float getFf() {
|
||||
return ff;
|
||||
}
|
||||
|
||||
public void setFf(Float ff) {
|
||||
this.ff = ff;
|
||||
}
|
||||
|
||||
public long getL() {
|
||||
return l;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* Copyright 2012-2016 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.
|
||||
@ -18,7 +18,11 @@
|
||||
*/
|
||||
package org.mapstruct.ap.test.conversion.numbers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.IterableMapping;
|
||||
import org.mapstruct.MapMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
@ -36,6 +40,8 @@ public interface SourceTargetMapper {
|
||||
@Mapping( target = "ii", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "d", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "dd", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "f", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "ff", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "l", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "ll", numberFormat = NUMBER_FORMAT ),
|
||||
@Mapping( target = "b", numberFormat = NUMBER_FORMAT ),
|
||||
@ -50,4 +56,19 @@ public interface SourceTargetMapper {
|
||||
|
||||
@InheritInverseConfiguration
|
||||
Source targetToSource(Target target);
|
||||
|
||||
@IterableMapping( numberFormat = NUMBER_FORMAT )
|
||||
List<String> sourceToTarget(List<Float> source);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
List<Float> targetToSource(List<String> source);
|
||||
|
||||
@MapMapping( keyNumberFormat = NUMBER_FORMAT, valueNumberFormat = "##" )
|
||||
Map<String, String> sourceToTarget(Map<Float, Float> source);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
Map<Float, Float> targetToSource(Map<String, String> source);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* Copyright 2012-2016 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.
|
||||
@ -24,6 +24,8 @@ public class Target {
|
||||
private String ii;
|
||||
private String d;
|
||||
private String dd;
|
||||
private String f;
|
||||
private String ff;
|
||||
private String l;
|
||||
private String ll;
|
||||
private String b;
|
||||
@ -67,6 +69,22 @@ public class Target {
|
||||
this.dd = dd;
|
||||
}
|
||||
|
||||
public String getF() {
|
||||
return f;
|
||||
}
|
||||
|
||||
public void setF(String f) {
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
public String getFf() {
|
||||
return ff;
|
||||
}
|
||||
|
||||
public void setFf(String ff) {
|
||||
this.ff = ff;
|
||||
}
|
||||
|
||||
public String getL() {
|
||||
return l;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user