vendredi 3 janvier 2020

Does using Enum as a fully featured object which makes use of dynamic dispatch like in this case mean misusing it or not a good design?

I have implemented a Role Enum which contains role definitions with ranks. For the getAssignableRoles() part, my colleague says that this is misusing the Enum or over engineering and states that it is not readable with this form.

public enum Role {
    USER("ROLE_user", 1),
    CUSTOMER("ROLE_customer", 2),
    PRODUCT_OWNER("ROLE_product_manager", 3) {
        @Override
        public List<Role> getAssignableRoles() {
            return getLowerRankedRoles().stream().filter(e -> !e.equals(CUSTOMER_ADMIN)).collect(Collectors.toList());
        }
    },
    CUSTOMER_ADMIN("ROLE_customer_admin", 3) { 
        @Override
        public List<Role> getAssignableRoles() {
            return getLowerRankedRoles().stream().filter(e -> !e.equals(PRODUCT_OWNER)).collect(Collectors.toList());
        }
    },
    USER_MANAGER("ROLE_user_manager", 5),
    ADMIN("ROLE_admin", 99);

    private final String value;
    private final int rank;

    public String getValue() {
        return value;
    }
    public int getRank() {
        return rank;
    }

    Role(String value, int rank) {
        this.value = value;
        this.rank = rank;
    }

    public static Role findByAbbr(String abbr) {
        return Arrays.stream(values()).filter(value -> value.value.equals(abbr)).findFirst().orElse(UNKNOWN);
    }

    public String getExactValue() {
        return value.replaceFirst("^ROLE_", "");
    }

    // Each role has a distinct grant rank but for some roles even if they have same grant level their role assigning changes in the context.
    public List<Role> getAssignableRoles() {
        return getLowerRankedRoles();
    }

    protected List<Role> getLowerRankedRoles() {
        return Arrays.stream(values()).filter(value -> value.rank <= rank).collect(Collectors.toList());
    }

    public static Predicate<String> isInRealm() {
         return (String role) -> (Arrays.stream(values()).anyMatch(value -> value.value.equals(role)));
    }

}

What I am trying to do was, in the client code to be able to call it like

Role.findByAbbr(role).getAssignableRoles()

Is using Enums like that is a good practice or design? Can we get most of dynamic dispatch features from Enum?

Aucun commentaire:

Enregistrer un commentaire