Skip to content

Instantly share code, notes, and snippets.

@chaotic3quilibrium
Last active October 26, 2023 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chaotic3quilibrium/f70cc24e855ab18a2b13f557dbf356d3 to your computer and use it in GitHub Desktop.
Save chaotic3quilibrium/f70cc24e855ab18a2b13f557dbf356d3 to your computer and use it in GitHub Desktop.
Solution to Java Enum Generics Problem Posted on StackOverflow
package org.public_domain.enum_ops_plus_id;
public interface DbIdEnum<T> {
T getDbId();
}
package org.public_domain.enum_ops_plus_id;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class DbIdEnumOps<E extends Enum<E> & DbIdEnum<T>, T> {
private final Map<T, E> enumValueByDbId;
private final Map<String, E> enumValueByNameLowerCaseOrDbId;
public static <E extends Enum<E> & DbIdEnum<T>, T> DbIdEnumOps<E, T> from(Class<E> enumClassE) {
return new DbIdEnumOps<>(enumClassE);
}
private DbIdEnumOps(Class<E> enumClassE) {
//how to validate AT COMPILE TIME `enumClassE` also conforms to `Class<EE>`?
var enumOpsList =
EnumOps.from(Objects.requireNonNull(enumClassE))
.toList();
this.enumValueByDbId =
Collections.unmodifiableMap(
enumOpsList
.stream()
.map(e -> Map.entry(e.getDbId(), e))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
this.enumValueByNameLowerCaseOrDbId =
Collections.unmodifiableMap(
enumOpsList
.stream()
.flatMap(e -> Stream.of(
Map.entry(e.name().toLowerCase(), e),
Map.entry(e.getDbId().toString(), e)))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)));
}
public Map<T, E> getEnumValueByDbId() {
return this.enumValueByDbId;
}
public Map<String, E> getEnumValueByNameLowerCaseOrDbId() {
return this.enumValueByNameLowerCaseOrDbId;
}
}
package org.public_domain.enum_ops_plus_id;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class EnumOps<E extends Enum<E>> {
private final Class<E> enumClass;
private final List<E> enumsValues;
private EnumOps(Class<E> enumClass) {
this.enumClass = enumClass;
this.enumsValues = Collections.unmodifiableList(Arrays.asList(enumClass.getEnumConstants()));
}
public static <E extends Enum<E>> EnumOps<E> from(Class<E> enumClass) {
return new EnumOps<>(enumClass);
}
public Class<E> getEnumClass() {
return this.enumClass;
}
public List<E> toList() {
return this.enumsValues;
}
//omitted lots of other helpful enum utilities that ought to have been provided by the Java compiler by default
}
package org.public_domain.enum_ops_plus_id;
public class Main {
public static void main(String[] args) {
var a = DbIdEnumOps.from(TrafficLight.class);
var b = DbIdEnumOps.<TrafficLight, Integer>from(TrafficLight.class);
DbIdEnumOps<TrafficLight, Integer> c = DbIdEnumOps.from(TrafficLight.class);
System.out.println("use me to set a breakpoint to examine the contents of the maps");
}
}
package org.public_domain.enum_ops_plus_id;
public enum TrafficLight implements DbIdEnum<Integer> {
GREEN(1),
YELLOW(2),
RED(3);
private final Integer dbId;
TrafficLight(Integer dbId) {
this.dbId = dbId;
}
private static final EnumOps<TrafficLight> enumOps =
EnumOps.from(TrafficLight.class);
private static final DbIdEnumOps<TrafficLight, Integer> dbIdEnumOpsA =
DbIdEnumOps.from(TrafficLight.class);
public static EnumOps<TrafficLight> ops() {
return enumOps;
}
public static DbIdEnumOps<TrafficLight, Integer> dbIdOps() {
return dbIdEnumOpsA;
}
public Integer getDbId() {
return this.dbId;
}
}
//StackOverflow Question: https://stackoverflow.com/q/77362860/501113
//Updated/fixed the 5 code files to incorporate the answer by Turing85: https://stackoverflow.com/users/4216641/turing85
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment