diff --git a/core-jdk8/src/main/java/org/mapstruct/Mapping.java b/core-jdk8/src/main/java/org/mapstruct/Mapping.java index 484e7f4fc..d9c716fb2 100644 --- a/core-jdk8/src/main/java/org/mapstruct/Mapping.java +++ b/core-jdk8/src/main/java/org/mapstruct/Mapping.java @@ -42,8 +42,9 @@ public @interface Mapping { *
- * Either this attribute or {@link #source()} may be specified for a given mapping, but not both at the same time. - * If this attribute is given, the target property must be specified via {@link #target()}. + * Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping, + * but not two at the same time. If this attribute is given, the target property must be specified via + * {@link #target()}. * * @return A constant {@code String} constant specifying the value for the designated target property */ String constant() default ""; + /** + * An expression {@link String} based on which the specified target property is to be set. + * + * The format is determined by a type of expression. For instance: + * {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java + * expression in the designated {@link #target()} property. + *
+ * Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping, + * but not two at the same time. If this attribute is given, the target property must be specified via + * {@link #target()}. + * + * @return A constant {@code String} constant specifying the value for the designated target property + */ + String expression() default ""; } diff --git a/core/src/main/java/org/mapstruct/Mapping.java b/core/src/main/java/org/mapstruct/Mapping.java index 656775796..7bd95d7e3 100644 --- a/core/src/main/java/org/mapstruct/Mapping.java +++ b/core/src/main/java/org/mapstruct/Mapping.java @@ -40,8 +40,9 @@ public @interface Mapping { *
- * Either this attribute or {@link #source()} may be specified for a given mapping, but not both at the same time. - * If this attribute is given, the target property must be specified via {@link #target()}. + * Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping, + * but not two at the same time. If this attribute is given, the target property must be specified via + * {@link #target()}. * * @return A constant {@code String} constant specifying the value for the designated target property */ String constant() default ""; + /** + * An expression {@link String} based on which the specified target property is to be set. + * + * The format is determined by a type of expression. For instance: + * {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java + * expression in the designated {@link #target()} property. + *
+ * Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping,
+ * but not two at the same time. If this attribute is given, the target property must be specified via
+ * {@link #target()}.
+ *
+ * @return A constant {@code String} constant specifying the value for the designated target property
+ */
+ String expression() default "";
+
}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java
index 0b55374a2..bfa1effb2 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java
@@ -22,6 +22,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.annotation.processing.Messager;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
@@ -39,10 +41,14 @@ import org.mapstruct.ap.util.AnnotationProcessingException;
*/
public class Mapping {
+ private static final Pattern JAVA_EXPRESSION = Pattern.compile( "^java\\((.*)\\)$" );
+
private final String sourceName;
private final String sourceParameterName;
private final String sourcePropertyName;
private final String constant;
+ private final String expression;
+ private final String javaExpression;
private final String targetName;
private final String dateFormat;
private final AnnotationMirror mirror;
@@ -74,10 +80,12 @@ public class Mapping {
mappingPrism.values.source()
);
- if ( mappingPrism.source().isEmpty() && mappingPrism.constant().isEmpty() ) {
+ if ( mappingPrism.source().isEmpty() &&
+ mappingPrism.constant().isEmpty() &&
+ mappingPrism.expression().isEmpty() ) {
messager.printMessage(
Diagnostic.Kind.ERROR,
- "Either define a source or a constant in a Mapping",
+ "Either define a source, a constant or an epression in a Mapping",
element
);
return null;
@@ -85,17 +93,33 @@ public class Mapping {
else if ( !mappingPrism.source().isEmpty() && !mappingPrism.constant().isEmpty() ) {
messager.printMessage(
Diagnostic.Kind.ERROR,
- "Source and constant are both defined in Mapping, either define a source or an expression",
+ "Source and constant are both defined in Mapping, either define a source or a constant",
+ element
+ );
+ return null;
+ }
+ else if ( !mappingPrism.source().isEmpty() && !mappingPrism.expression().isEmpty() ) {
+ messager.printMessage(
+ Diagnostic.Kind.ERROR,
+ "Source and expression are both defined in Mapping, either define a source or an expression",
+ element
+ );
+ return null;
+ }
+ else if ( !mappingPrism.expression().isEmpty() && !mappingPrism.constant().isEmpty() ) {
+ messager.printMessage(
+ Diagnostic.Kind.ERROR,
+ "Expression and constant are both defined in Mapping, either define an expression or a constant",
element
);
return null;
}
-
return new Mapping(
mappingPrism.source(),
sourceNameParts != null ? sourceNameParts[0] : null,
sourceNameParts != null ? sourceNameParts[1] : mappingPrism.source(),
mappingPrism.constant(),
+ mappingPrism.expression(),
mappingPrism.target(),
mappingPrism.dateFormat(),
mappingPrism.mirror,
@@ -124,12 +148,15 @@ public class Mapping {
}
private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String constant,
- String targetName, String dateFormat, AnnotationMirror mirror,
+ String expression, String targetName, String dateFormat, AnnotationMirror mirror,
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue) {
this.sourceName = sourceName;
this.sourceParameterName = sourceParameterName;
this.sourcePropertyName = sourcePropertyName;
this.constant = constant;
+ this.expression = expression;
+ Matcher javaExpressionMatcher = JAVA_EXPRESSION.matcher( expression );
+ this.javaExpression = javaExpressionMatcher.matches() ? javaExpressionMatcher.group( 1 ) : "";
this.targetName = targetName.equals( "" ) ? sourceName : targetName;
this.dateFormat = dateFormat;
this.mirror = mirror;
@@ -169,6 +196,9 @@ public class Mapping {
return constant;
}
+ public String getJavaExpression() {
+ return javaExpression;
+ }
public String getTargetName() {
return targetName;
@@ -200,6 +230,7 @@ public class Mapping {
null,
targetName,
constant,
+ expression,
sourceName,
dateFormat,
mirror,
diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java
index 5ed19ab1b..4e917ced7 100644
--- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java
@@ -406,13 +406,30 @@ public class MapperCreationProcessor implements ModelElementProcessor sourceGetters = parameter.getType().getGetters();
- // check constants first
- if ( isSourceConstant ) {
- return getConstantMapping(
- mapperReferences,
- methods,
- method,
- sourceConstant,
- targetAccessor,
- dateFormat
- );
- }
-
// then iterate over source accessors (assuming the source is a bean)
for ( ExecutableElement sourceAccessor : sourceGetters ) {
@@ -676,6 +681,7 @@ public class MapperCreationProcessor implements ModelElementProcessor
methods,
SourceMethod method,
String constantExpression,
- ExecutableElement targetAcessor,
+ ExecutableElement targetAccessor,
String dateFormat) {
// source
@@ -851,14 +857,8 @@ public class MapperCreationProcessor implements ModelElementProcessor