Java annotation processor for the generation of type-safe bean mappers
—
Advanced enum mapping capabilities supporting value transformations, name transformations, and comprehensive error handling for unmapped values.
Configures explicit mapping of individual enum constants.
/**
* Configures the mapping of one enum constant to another.
*/
@Repeatable(ValueMappings.class)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface ValueMapping {
/** Source enum constant name */
String source();
/** Target enum constant name */
String target();
}Usage Examples:
// Source enum
public enum OrderStatus {
PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED
}
// Target enum
public enum PublicOrderStatus {
WAITING, PROCESSING, IN_TRANSIT, COMPLETED, CANCELLED
}
@Mapper
public interface EnumMapper {
// Explicit value mappings
@ValueMapping(source = "PENDING", target = "WAITING")
@ValueMapping(source = "CONFIRMED", target = "PROCESSING")
@ValueMapping(source = "SHIPPED", target = "IN_TRANSIT")
@ValueMapping(source = "DELIVERED", target = "COMPLETED")
@ValueMapping(source = "CANCELLED", target = "CANCELLED")
PublicOrderStatus toPublicStatus(OrderStatus status);
// Inverse mapping
@ValueMapping(source = "WAITING", target = "PENDING")
@ValueMapping(source = "PROCESSING", target = "CONFIRMED")
@ValueMapping(source = "IN_TRANSIT", target = "SHIPPED")
@ValueMapping(source = "COMPLETED", target = "DELIVERED")
@ValueMapping(source = "CANCELLED", target = "CANCELLED")
OrderStatus toInternalStatus(PublicOrderStatus status);
}Special constants for handling null values and unmapped enum constants.
/**
* Mapping constants for special enum mapping scenarios.
*/
class MappingConstants {
/** Represents null in value mappings */
public static final String NULL = "<NULL>";
/** Catch-all for unmapped enum values */
public static final String ANY_REMAINING = "<ANY_REMAINING>";
/** Catch-all without name-based mapping */
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
/** Throw exception for unmapped values */
public static final String THROW_EXCEPTION = "<THROW_EXCEPTION>";
}Usage Examples:
@Mapper
public interface SpecialValueMapper {
// Handle null values
@ValueMapping(source = MappingConstants.NULL, target = "UNKNOWN")
@ValueMapping(source = "ACTIVE", target = "ENABLED")
@ValueMapping(source = "INACTIVE", target = "DISABLED")
TargetStatus mapWithNullHandling(SourceStatus status);
// Handle unmapped values with default
@ValueMapping(source = "CONFIRMED", target = "PROCESSED")
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = "OTHER")
SimpleStatus mapWithDefault(ComplexStatus status);
// Throw exception for unmapped values
@ValueMapping(source = "SUCCESS", target = "OK")
@ValueMapping(source = "FAILURE", target = "ERROR")
@ValueMapping(source = MappingConstants.ANY_UNMAPPED, target = MappingConstants.THROW_EXCEPTION)
ResultStatus mapWithException(ProcessStatus status);
// Map null to null
@ValueMapping(source = MappingConstants.NULL, target = MappingConstants.NULL)
@ValueMapping(source = "ENABLED", target = "ACTIVE")
@ValueMapping(source = "DISABLED", target = "INACTIVE")
Status mapNullToNull(Status status);
}Configures enum transformation strategies for automatic name transformations.
/**
* Configures the mapping between two enum types.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface EnumMapping {
/** Name transformation strategy */
String nameTransformationStrategy() default "";
/** Configuration for the transformation strategy */
String configuration() default "";
/** Exception to throw for unmapped enum values */
Class<? extends Exception> unexpectedValueMappingException() default IllegalArgumentException.class;
}Transformation Strategy Constants:
/**
* Constants for enum name transformation strategies.
*/
class MappingConstants {
/** Add suffix to enum names */
public static final String SUFFIX_TRANSFORMATION = "suffix";
/** Add prefix to enum names */
public static final String PREFIX_TRANSFORMATION = "prefix";
/** Remove suffix from enum names */
public static final String STRIP_SUFFIX_TRANSFORMATION = "stripSuffix";
/** Remove prefix from enum names */
public static final String STRIP_PREFIX_TRANSFORMATION = "stripPrefix";
/** Transform case of enum names */
public static final String CASE_TRANSFORMATION = "case";
}Usage Examples:
// Source enum
public enum DatabaseStatus {
DB_CONNECTED, DB_DISCONNECTED, DB_ERROR
}
// Target enum
public enum Status {
CONNECTED, DISCONNECTED, ERROR
}
@Mapper
public interface TransformationMapper {
// Strip prefix transformation
@EnumMapping(
nameTransformationStrategy = MappingConstants.STRIP_PREFIX_TRANSFORMATION,
configuration = "DB_"
)
Status mapDatabaseStatus(DatabaseStatus status);
// Add suffix transformation
@EnumMapping(
nameTransformationStrategy = MappingConstants.SUFFIX_TRANSFORMATION,
configuration = "_STATE"
)
StatusState addSuffixToStatus(Status status);
// Case transformation
@EnumMapping(
nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION,
configuration = "lower"
)
LowerCaseStatus toLowerCase(UpperCaseStatus status);
// Custom exception for unmapped values
@EnumMapping(
unexpectedValueMappingException = IllegalStateException.class
)
@ValueMapping(source = "KNOWN", target = "MAPPED")
MappedStatus mapWithCustomException(UnknownStatus status);
}Container annotation for multiple @ValueMapping annotations.
/**
* Used to hold multiple @ValueMapping annotations.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface ValueMappings {
/** The value mapping configurations */
ValueMapping[] value();
}Usage Example:
@Mapper
public interface LegacyEnumMapper {
// Pre-Java 8 style multiple value mappings
@ValueMappings({
@ValueMapping(source = "DRAFT", target = "PENDING"),
@ValueMapping(source = "PUBLISHED", target = "ACTIVE"),
@ValueMapping(source = "ARCHIVED", target = "INACTIVE")
})
DocumentStatus toDocumentStatus(ContentStatus status);
}Advanced patterns for complex enum mapping requirements.
Usage Examples:
// Enums with different structures
public enum DetailedStatus {
INITIAL_DRAFT, PENDING_REVIEW, APPROVED_FOR_PUBLISH, PUBLISHED_LIVE, ARCHIVED_INACTIVE
}
public enum SimpleStatus {
DRAFT, REVIEW, APPROVED, LIVE, ARCHIVED
}
@Mapper
public interface ComplexEnumMapper {
// Complex mappings with transformations and explicit mappings
@EnumMapping(
nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION,
configuration = "_DRAFT|_REVIEW|_FOR_PUBLISH|_LIVE|_INACTIVE"
)
@ValueMapping(source = "INITIAL_DRAFT", target = "DRAFT")
@ValueMapping(source = "PENDING_REVIEW", target = "REVIEW")
@ValueMapping(source = "APPROVED_FOR_PUBLISH", target = "APPROVED")
@ValueMapping(source = "PUBLISHED_LIVE", target = "LIVE")
@ValueMapping(source = "ARCHIVED_INACTIVE", target = "ARCHIVED")
SimpleStatus simplifyStatus(DetailedStatus status);
// Bidirectional mapping
@ValueMapping(source = "DRAFT", target = "INITIAL_DRAFT")
@ValueMapping(source = "REVIEW", target = "PENDING_REVIEW")
@ValueMapping(source = "APPROVED", target = "APPROVED_FOR_PUBLISH")
@ValueMapping(source = "LIVE", target = "PUBLISHED_LIVE")
@ValueMapping(source = "ARCHIVED", target = "ARCHIVED_INACTIVE")
DetailedStatus expandStatus(SimpleStatus status);
}Using qualifiers to select specific enum mapping methods.
Usage Examples:
@Mapper
public interface QualifiedEnumMapper {
// Method-level qualifier
@Named("toPublicStatus")
@ValueMapping(source = "INTERNAL_PROCESSING", target = "PROCESSING")
@ValueMapping(source = "INTERNAL_ERROR", target = "ERROR")
PublicStatus toPublicStatus(InternalStatus status);
// Using qualified enum mapper in bean mapping
@Mapping(source = "status", target = "publicStatus", qualifiedByName = "toPublicStatus")
OrderDto mapOrder(Order order);
}
// Custom qualifier annotation
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface PublicApi {
}
@Mapper
public interface CustomQualifiedMapper {
@PublicApi
@ValueMapping(source = "ADMIN_ONLY", target = "RESTRICTED")
@ValueMapping(source = "PUBLIC", target = "AVAILABLE")
AccessLevel toPublicAccessLevel(InternalAccessLevel level);
@Mapping(source = "accessLevel", target = "publicAccess", qualifiedBy = PublicApi.class)
ResourceDto mapResource(Resource resource);
}Comprehensive error handling for enum mapping edge cases.
Usage Examples:
@Mapper
public interface ErrorHandlingEnumMapper {
// Default exception (IllegalArgumentException)
@ValueMapping(source = "KNOWN", target = "MAPPED")
@ValueMapping(source = MappingConstants.ANY_UNMAPPED, target = MappingConstants.THROW_EXCEPTION)
TargetEnum mapWithDefaultException(SourceEnum source);
// Custom exception
@EnumMapping(unexpectedValueMappingException = UnsupportedOperationException.class)
@ValueMapping(source = "SUPPORTED", target = "ENABLED")
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = MappingConstants.THROW_EXCEPTION)
FeatureStatus mapWithCustomException(FeatureFlag flag);
// Safe mapping with default fallback
@ValueMapping(source = "SUCCESS", target = "OK")
@ValueMapping(source = "WARNING", target = "CAUTION")
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = "UNKNOWN")
Result mapSafely(Status status);
}Install with Tessl CLI
npx tessl i tessl/maven-org-mapstruct--mapstruct