1414import java .util .Set ;
1515import javax .lang .model .element .TypeElement ;
1616import javax .lang .model .type .TypeMirror ;
17- import org .mapstruct .ap .internal .util .TypeUtils ;
1817
1918import org .mapstruct .ap .internal .gem .BeanMappingGem ;
2019import org .mapstruct .ap .internal .model .common .Parameter ;
2524import org .mapstruct .ap .internal .model .source .ValueMappingOptions ;
2625import org .mapstruct .ap .internal .util .Message ;
2726import org .mapstruct .ap .internal .util .Strings ;
27+ import org .mapstruct .ap .internal .util .TypeUtils ;
2828import org .mapstruct .ap .spi .EnumTransformationStrategy ;
2929
3030import static org .mapstruct .ap .internal .gem .MappingConstantsGem .ANY_REMAINING ;
3131import static org .mapstruct .ap .internal .gem .MappingConstantsGem .ANY_UNMAPPED ;
3232import static org .mapstruct .ap .internal .gem .MappingConstantsGem .NULL ;
33+ import static org .mapstruct .ap .internal .gem .MappingConstantsGem .THROW_EXCEPTION ;
3334import static org .mapstruct .ap .internal .util .Collections .first ;
3435
3536/**
@@ -43,6 +44,8 @@ public class ValueMappingMethod extends MappingMethod {
4344 private final List <MappingEntry > valueMappings ;
4445 private final String defaultTarget ;
4546 private final String nullTarget ;
47+ private boolean nullAsException ;
48+ private boolean defaultAsException ;
4649
4750 private final Type unexpectedValueMappingException ;
4851
@@ -119,10 +122,12 @@ else if ( sourceType.isString() && targetType.isEnumType() ) {
119122 return new ValueMappingMethod ( method ,
120123 mappingEntries ,
121124 valueMappings .nullValueTarget ,
125+ valueMappings .hasNullValueAsException ,
122126 valueMappings .defaultTargetValue ,
123127 determineUnexpectedValueMappingException (),
124128 beforeMappingMethods ,
125- afterMappingMethods
129+ afterMappingMethods ,
130+ determineExceptionMappingForDefaultCase ()
126131 );
127132 }
128133
@@ -313,7 +318,17 @@ private boolean reportErrorIfMappedSourceEnumConstantsDontExist(Method method, T
313318
314319 for ( ValueMappingOptions mappedConstant : valueMappings .regularValueMappings ) {
315320
316- if ( !sourceEnumConstants .contains ( mappedConstant .getSource () ) ) {
321+ if ( !enumMapping .isInverse () && THROW_EXCEPTION .equals ( mappedConstant .getSource () ) ) {
322+ ctx .getMessager ().printMessage (
323+ method .getExecutable (),
324+ mappedConstant .getMirror (),
325+ mappedConstant .getSourceAnnotationValue (),
326+ Message .VALUEMAPPING_THROW_EXCEPTION_SOURCE
327+ );
328+ foundIncorrectMapping = true ;
329+ }
330+ else if ( !sourceEnumConstants .contains ( mappedConstant .getSource () ) ) {
331+
317332 ctx .getMessager ().printMessage (
318333 method .getExecutable (),
319334 mappedConstant .getMirror (),
@@ -361,6 +376,7 @@ private boolean reportErrorIfMappedTargetEnumConstantsDontExist(Method method, T
361376
362377 for ( ValueMappingOptions mappedConstant : valueMappings .regularValueMappings ) {
363378 if ( !NULL .equals ( mappedConstant .getTarget () )
379+ && !THROW_EXCEPTION .equals ( mappedConstant .getTarget () )
364380 && !targetEnumConstants .contains ( mappedConstant .getTarget () ) ) {
365381 ctx .getMessager ().printMessage (
366382 method .getExecutable (),
@@ -374,7 +390,9 @@ private boolean reportErrorIfMappedTargetEnumConstantsDontExist(Method method, T
374390 }
375391 }
376392
377- if ( valueMappings .defaultTarget != null && !NULL .equals ( valueMappings .defaultTarget .getTarget () )
393+ if ( valueMappings .defaultTarget != null
394+ && !THROW_EXCEPTION .equals ( valueMappings .defaultTarget .getTarget () )
395+ && !NULL .equals ( valueMappings .defaultTarget .getTarget () )
378396 && !targetEnumConstants .contains ( valueMappings .defaultTarget .getTarget () ) ) {
379397 ctx .getMessager ().printMessage (
380398 method .getExecutable (),
@@ -415,7 +433,9 @@ else if ( valueMappings.nullTarget == null && valueMappings.nullValueTarget != n
415433 }
416434
417435 private Type determineUnexpectedValueMappingException () {
418- if ( !valueMappings .hasDefaultValue ) {
436+ boolean noDefaultValueForSwitchCase = !valueMappings .hasDefaultValue ;
437+ if ( noDefaultValueForSwitchCase || valueMappings .hasAtLeastOneExceptionValue
438+ || valueMappings .hasNullValueAsException ) {
419439 TypeMirror unexpectedValueMappingException = enumMapping .getUnexpectedValueMappingException ();
420440 if ( unexpectedValueMappingException != null ) {
421441 return ctx .getTypeFactory ().getType ( unexpectedValueMappingException );
@@ -427,6 +447,15 @@ private Type determineUnexpectedValueMappingException() {
427447
428448 return null ;
429449 }
450+
451+ private boolean determineExceptionMappingForDefaultCase () {
452+ if ( valueMappings .hasDefaultValue ) {
453+ return THROW_EXCEPTION .equals ( valueMappings .defaultTargetValue );
454+ }
455+ else {
456+ return true ;
457+ }
458+ }
430459 }
431460
432461 private static class EnumTransformationStrategyInvoker {
@@ -464,7 +493,8 @@ private static class ValueMappings {
464493 boolean hasMapAnyUnmapped = false ;
465494 boolean hasMapAnyRemaining = false ;
466495 boolean hasDefaultValue = false ;
467- boolean hasNullValue = false ;
496+ boolean hasNullValueAsException = false ;
497+ boolean hasAtLeastOneExceptionValue = false ;
468498
469499 ValueMappings (List <ValueMappingOptions > valueMappings ) {
470500
@@ -484,11 +514,17 @@ else if ( ANY_UNMAPPED.equals( valueMapping.getSource() ) ) {
484514 else if ( NULL .equals ( valueMapping .getSource () ) ) {
485515 nullTarget = valueMapping ;
486516 nullValueTarget = getValue ( nullTarget );
487- hasNullValue = true ;
517+ if ( THROW_EXCEPTION .equals ( nullValueTarget ) ) {
518+ hasNullValueAsException = true ;
519+ }
488520 }
489521 else {
490522 regularValueMappings .add ( valueMapping );
491523 }
524+
525+ if ( THROW_EXCEPTION .equals ( valueMapping .getTarget () ) ) {
526+ hasAtLeastOneExceptionValue = true ;
527+ }
492528 }
493529 }
494530
@@ -497,14 +533,20 @@ String getValue(ValueMappingOptions valueMapping) {
497533 }
498534 }
499535
500- private ValueMappingMethod (Method method , List <MappingEntry > enumMappings , String nullTarget , String defaultTarget ,
501- Type unexpectedValueMappingException ,
502- List <LifecycleCallbackMethodReference > beforeMappingMethods ,
503- List <LifecycleCallbackMethodReference > afterMappingMethods ) {
536+ private ValueMappingMethod (Method method ,
537+ List <MappingEntry > enumMappings ,
538+ String nullTarget ,
539+ boolean hasNullTargetAsException ,
540+ String defaultTarget ,
541+ Type unexpectedValueMappingException ,
542+ List <LifecycleCallbackMethodReference > beforeMappingMethods ,
543+ List <LifecycleCallbackMethodReference > afterMappingMethods , boolean defaultAsException ) {
504544 super ( method , beforeMappingMethods , afterMappingMethods );
505545 this .valueMappings = enumMappings ;
506546 this .nullTarget = nullTarget ;
547+ this .nullAsException = hasNullTargetAsException ;
507548 this .defaultTarget = defaultTarget ;
549+ this .defaultAsException = defaultAsException ;
508550 this .unexpectedValueMappingException = unexpectedValueMappingException ;
509551 this .overridden = method .overridesMethod ();
510552 }
@@ -532,10 +574,18 @@ public String getNullTarget() {
532574 return nullTarget ;
533575 }
534576
577+ public boolean isNullAsException () {
578+ return nullAsException ;
579+ }
580+
535581 public Type getUnexpectedValueMappingException () {
536582 return unexpectedValueMappingException ;
537583 }
538584
585+ public boolean isDefaultAsException () {
586+ return defaultAsException ;
587+ }
588+
539589 public Parameter getSourceParameter () {
540590 return first ( getSourceParameters () );
541591 }
@@ -547,17 +597,25 @@ public boolean isOverridden() {
547597 public static class MappingEntry {
548598 private final String source ;
549599 private final String target ;
600+ private boolean targetAsException = false ;
550601
551- MappingEntry ( String source , String target ) {
602+ MappingEntry (String source , String target ) {
552603 this .source = source ;
553604 if ( !NULL .equals ( target ) ) {
554605 this .target = target ;
606+ if ( THROW_EXCEPTION .equals ( target ) ) {
607+ this .targetAsException = true ;
608+ }
555609 }
556610 else {
557611 this .target = null ;
558612 }
559613 }
560614
615+ public boolean isTargetAsException () {
616+ return targetAsException ;
617+ }
618+
561619 public String getSource () {
562620 return source ;
563621 }
0 commit comments