Git Product home page Git Product logo

enum-mapper's Introduction

Build Status license

enum-mapper

The main use: make sure that you always handle all available constants of an enum. An annotation processor will make sure that you get a compile-time error otherwise: see Full Enum Mapper.
You can also use a Partial Mapper and it supports Reverse Mapping.
Since version 1.4 Incremental Annotation Processing is supported for Gradle builds.

Build Configuration

The project is available in Maven Central and JCenter-Bintray repositories.

    final VERSION_ENUM_MAPPER = '1.0.4' // check for newer versions here: https://goo.gl/LSP1fv
    implementation  "com.tmtron.enums:enum-mapper-lib:${VERSION_ENUM_MAPPER}"
    annotationProcessor "com.tmtron.enums:enum-mapper-processor:${VERSION_ENUM_MAPPER}"

enum-mapper-lib

Contains java code and annotations.
This is always needed at compile-time.
Maven Central lib Javadocs

enum-mapper-processor

Contains the annotation-processor.
This is needed by the annotation-processing build-step (apt) and it is only required for the Full Enum Mapper.
Maven Central processor Javadocs

Full Enum Mapper

Just annotate your enum with the @EnumMapper annotation:

@EnumMapper
public enum Seasons {
  SPRING, SUMMER, FALL, WINTER
}

When you build your project, the annotation processor will generate a java class Seasons_MapperFull, which can be used to map all enum constants to arbitrary values.

Here is an example use where we map each enum constant to a string.

EnumMapperFull<Seasons, String> germanSeasons = Seasons_MapperFull
     .setSPRING("Fruehling")
     .setSUMMER("Sommer")
     .setFALL("Herbst")
     .setWINTER("Winter");

String germanSummer = germanSeasons.getValue(Seasons.SUMMER); // returns "Sommer"

The great thing about this is that you will get a compile time error, when you forget to map any enum-constant - or when you change the enumeration (e.g. add or remove an enum-constant).

Detailed usage examples are also available on the github enum-mapper-example project

Third party enums

You can also generate full-mappers for Enums that you don't control. Just add the @EnumMappers (note the plural form!) annotation to any class and reference the enum classes that you want to map.

For example let's assume, that you use a 3rd party library which defines these enums:

public enum ColorEnum {
    RED, BLUE, GREEN
}
public enum BoolEnum {
    ON, OFF
}

Since you cannot change the source code of the 3rd party library, you cannot add the @EnumMapper annotation to the enum classes.
Instead you can use the the @EnumMappers (note the plural form!) annotation on any of your own classes, like this:

@EnumMappers({ColorEnum.class, BoolEnum.class})
public class AppUtil {
    // your code here
}

Then the annotation processor will create a full enum-mapper for ColorEnum and for BoolEnum.

Hint: when you want to map a single enum, you don't need the curly braces (for the array-syntax)

@EnumMappers(ColorEnum.class)
public class AppUtil {
    // your code here
}

Partial Enum Mapper

The project also includes a partial enum-mapper class which you may want to use instead of a switch statement.
Note. The partial enum mapper does not need the annotation processor.

An example of a partial mapper for your Seasons enum:

    EnumMapperPartial<Seasons, String> extremeSeasons =
            EnumMapperPartial.of(SUMMER, "Sommer"
                    , WINTER, "Winter");

Now you can call the getValueOrNull or getValueOrDefault methods like this:

extremeSeasons.getValueOrNull(SUMMER);                      // returns "Sommer"
extremeSeasons.getValueOrNull(WINTER);                      // returns "Winter"
extremeSeasons.getValueOrNull(SPRING));                     // returns null
extremeSeasons.getValueOrDefault(SPRING, "not extreme");    // returns "not extreme"
extremeSeasons.getValueOrRaise(SPRING);                     // throws an IllegalArgumentException
extremeSeasons.isEnumMapped(SUMMER);                        // returns true
extremeSeasons.isEnumMapped(SPRING);                        // returns false

Reverse mapping

The full and the partial mappers also support reverse lookup.

For example, we can use the extremeSeasons mapper to get the enum-constant for a string, like this:

extremeSeasons.getEnumOrNull("Sommer");                 // returns the enum-constant SUMMER
extremeSeasons.getEnumOrDefault("Fruehling", FALL));    // returns the enum-constant FALL
extremeSeasons.getEnumOrRaise("Fruehling");             // throws an IllegalArgumentException 
extremeSeasons.isValueMapped("Sommer");                 // returns true
extremeSeasons.isValueMapped("Fruehling");              // returns false

When you do a reverse mapping the mapped values should of course be unique.

Alternatives

This section mentions some alternative approaches that you can use instead of this annotation processor.
See also: Stackoverflow: How to ensure completeness in an enum switch at compile time?

Abstract Enum Methods

As mentioned in this Stackoverflow answer you can have abstract methods on your enum definition.

public enum AlternativeBool {

    ON {
        @Override
        public String getGermanName() {
            return "ein";
        }
    }
    , OFF {
        @Override
        public String getGermanName() {
            return "aus";
        }
    };


    public abstract String getGermanName();
}

Advantages

  • this approach does not need an annotation processor
  • you also get a compile-time error should you forget to implement a method for a new enum

Disadvantages

  • it is quite verbose
  • you can only use this for enums that you control

IDE checks

Some IDEs allow you to activate a check that will warn you when you forget an enum constant in a switch statement:

Advantages

  • this approach does not need an annotation processor
  • direct and immediate feedback

Disadvantages

  • you could forget to active the switch
  • someone members of your team may use other IDEs which don't support this feature

Other tools

For example FindBugs has a check Switch statement found where default case is missing SF_SWITCH_NO_DEFAULT

Advantages

  • other tools may offer way more functionality

Disadvantages

  • those are other tools that you must learn to use and maintain

License

This plugin is under the Apache 2.0 license. Copyright 2018, Martin Trummer

enum-mapper's People

Contributors

tmtron avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

enum-mapper's Issues

add isEnumMapped + isValueMapped methods

add the following methods EnumMapperBase:

  • boolean hasMappingForValue(V value)
  • boolean hasMappingForEnum(K enumConstant): note: this will always return true fro EnumMapperFull

duplicate enums in @EnumMappers should be ignored

For larger applications it can be useful to have duplicate @EnumMappers annotations in different packages.

Example:

package com.test.featureA;

@EnumMappers(ColorEnum.class)
public static class FeatureA {
}
package com.test.featureB;

@EnumMappers(ColorEnum.class)
public static class FeatureB {
}

The annotation processor should allow this and the origin (in the comment of the @Generated annotation) should use array-syntax, like this:

@Generated(
        value = "com.tmtron.enums.processor.EnumsAnnotationProcessor",
        date = "1976-12-14T15:16:17.234+02:00",
        comments = "origin=[com.test.featureA.FeatureA,com.test.featureB.FeatureB]"
)
public final class BoolEnum_MapperFull {
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.