Repository: graphhopper/graphhopper
Pull request #1570 (2019-03-11 13:38:43)

trying cleaner enums again 
In #1548 we stumbled again over type safety problems and so it might be a good idea before publishing 0.12 to reintroduces enums instead of the self-made IndexBased interface. Everything should be possible with Enums too and if more values are required of e.g. `surface` or `road_class` it is best to create a completely new type/enum or submit a PR to change this in GH core.

Related #1447 

TODOs:

 - [x] Is it acceptable that we have to rewrite the TagParser just because we want to extend the `RoadClass` values? For `RoadClass` probably yes (has also the advantage of type safety within the TagParser), but what about `Surface` where we probably do not want to use too many bits but others maybe want to invest more. Solution: we could introduce a find method in the TagParser that subclasses could overwrite and then use `T extends RoadClass` or just Enums in the parsing method.
 - [x] is IntEncodedValue sufficient for `Country`?
 - [x] introduce new type safe lookup method like `getEnumEncodedValue(String key, Class type)`? Currently we have just `getEnumEncodedValue(String key)`
 - [x] method name in EnumEncodedValue? setObject vs. set vs. setEnum
 - [x] ~path details name?~ (only #1548 is affected) ObjectDetails vs. EnumDetails



Patch:
diff --git a/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java
index 7c0eb1bcd..c873f90e5 100644
--- a/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java
+++ b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java
@@ -17,7 +17,10 @@
  */
 package com.graphhopper.routing;
 
-import com.graphhopper.routing.profiles.*;
+import com.graphhopper.routing.profiles.BooleanEncodedValue;
+import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EnumEncodedValue;
+import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.util.CHEdgeIteratorState;
 import com.graphhopper.util.EdgeIterator;
@@ -177,24 +180,24 @@ class VirtualEdgeIterator implements EdgeIterator, CHEdgeIteratorState {
     }
 
     @Override
-    public EdgeIteratorState set(ObjectEncodedValue property, IndexBased value) {
+    public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
         edges.get(current).set(property, value);
         return this;
     }
 
     @Override
-    public IndexBased get(ObjectEncodedValue property) {
+    public <T extends Enum> T get(EnumEncodedValue<T> property) {
         return edges.get(current).get(property);
     }
 
     @Override
-    public EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value) {
+    public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
         edges.get(current).setReverse(property, value);
         return this;
     }
 
     @Override
-    public IndexBased getReverse(ObjectEncodedValue property) {
+    public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
         return edges.get(current).getReverse(property);
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/VirtualEdgeIteratorState.java b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIteratorState.java
index 439fa2c42..61725d279 100644
--- a/core/src/main/java/com/graphhopper/routing/VirtualEdgeIteratorState.java
+++ b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIteratorState.java
@@ -17,7 +17,10 @@
  */
 package com.graphhopper.routing;
 
-import com.graphhopper.routing.profiles.*;
+import com.graphhopper.routing.profiles.BooleanEncodedValue;
+import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EnumEncodedValue;
+import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.util.CHEdgeIteratorState;
 import com.graphhopper.util.EdgeIteratorState;
@@ -200,24 +203,24 @@ public class VirtualEdgeIteratorState implements EdgeIteratorState, CHEdgeIterat
     }
 
     @Override
-    public IndexBased get(ObjectEncodedValue property) {
-        return property.getObject(reverse, edgeFlags);
+    public <T extends Enum> T get(EnumEncodedValue<T> property) {
+        return property.getEnum(reverse, edgeFlags);
     }
 
     @Override
-    public EdgeIteratorState set(ObjectEncodedValue property, IndexBased value) {
-        property.setObject(reverse, edgeFlags, value);
+    public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
+        property.setEnum(reverse, edgeFlags, value);
         return this;
     }
 
     @Override
-    public IndexBased getReverse(ObjectEncodedValue property) {
-        return property.getObject(!reverse, edgeFlags);
+    public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
+        return property.getEnum(!reverse, edgeFlags);
     }
 
     @Override
-    public EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value) {
-        property.setObject(!reverse, edgeFlags, value);
+    public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
+        property.setEnum(!reverse, edgeFlags, value);
         return this;
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/profiles/EncodedValueLookup.java b/core/src/main/java/com/graphhopper/routing/profiles/EncodedValueLookup.java
index 15ebf2d2d..5588bea28 100644
--- a/core/src/main/java/com/graphhopper/routing/profiles/EncodedValueLookup.java
+++ b/core/src/main/java/com/graphhopper/routing/profiles/EncodedValueLookup.java
@@ -27,7 +27,7 @@ public interface EncodedValueLookup {
 
     DecimalEncodedValue getDecimalEncodedValue(String key);
 
-    ObjectEncodedValue getObjectEncodedValue(String key);
+    <T extends Enum> EnumEncodedValue<T> getEnumEncodedValue(String key, Class<T> enumType);
 
     boolean hasEncoder(String key);
 }
diff --git a/core/src/main/java/com/graphhopper/routing/profiles/MappedObjectEncodedValue.java b/core/src/main/java/com/graphhopper/routing/profiles/EnumEncodedValue.java
similarity index 62%
rename from core/src/main/java/com/graphhopper/routing/profiles/MappedObjectEncodedValue.java
rename to core/src/main/java/com/graphhopper/routing/profiles/EnumEncodedValue.java
index 9c07e7b0e..51d1c8e59 100644
--- a/core/src/main/java/com/graphhopper/routing/profiles/MappedObjectEncodedValue.java
+++ b/core/src/main/java/com/graphhopper/routing/profiles/EnumEncodedValue.java
@@ -19,29 +19,24 @@ package com.graphhopper.routing.profiles;
 
 import com.graphhopper.storage.IntsRef;
 
-import java.util.List;
-
 /**
- * This class implements an ObjectEncodedValue and holds an array of IndexBased objects. It stores just the indices
+ * This class implements an ObjectEncodedValue via a list of enums. I.e. it stores just the indices
  * of the used objects as an integer value.
  */
-public final class MappedObjectEncodedValue extends SimpleIntEncodedValue implements ObjectEncodedValue {
-    private final IndexBased[] arr;
-
-    public MappedObjectEncodedValue(String name, List<? extends IndexBased> values) {
-        super(name, 32 - Integer.numberOfLeadingZeros(values.size()));
+public final class EnumEncodedValue<E extends Enum> extends SimpleIntEncodedValue {
+    private final E[] arr;
 
-        arr = values.toArray(new IndexBased[]{});
+    public EnumEncodedValue(String name, Class<E> enumType) {
+        super(name, 32 - Integer.numberOfLeadingZeros(enumType.getEnumConstants().length));
+        arr = enumType.getEnumConstants();
     }
 
-    @Override
-    public final void setObject(boolean reverse, IntsRef ref, IndexBased value) {
+    public final void setEnum(boolean reverse, IntsRef ref, E value) {
         int intValue = value.ordinal();
         super.setInt(reverse, ref, intValue);
     }
 
-    @Override
-    public final IndexBased getObject(boolean reverse, IntsRef ref) {
+    public final E getEnum(boolean reverse, IntsRef ref) {
         int value = super.getInt(reverse, ref);
         return arr[value];
     }
diff --git a/core/src/main/java/com/graphhopper/routing/profiles/IndexBased.java b/core/src/main/java/com/graphhopper/routing/profiles/IndexBased.java
deleted file mode 100644
index a2203640c..000000000
--- a/core/src/main/java/com/graphhopper/routing/profiles/IndexBased.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.graphhopper.routing.profiles;
-
-/**
- * This interface ensures that at least one method is defined: the index the object should get in an array, to store
- * objects with only few keys in a compact form. We can't use enums as they are not extendable nor customizable.
- */
-public interface IndexBased {
-    int ordinal();
-}
diff --git a/core/src/main/java/com/graphhopper/routing/profiles/ObjectEncodedValue.java b/core/src/main/java/com/graphhopper/routing/profiles/ObjectEncodedValue.java
deleted file mode 100644
index ef255f8a6..000000000
--- a/core/src/main/java/com/graphhopper/routing/profiles/ObjectEncodedValue.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.graphhopper.routing.profiles;
-
-import com.graphhopper.storage.IntsRef;
-
-/**
- * This interface provides access to an EncodedValue of an index based object
- *
- * @see IndexBased
- */
-public interface ObjectEncodedValue extends EncodedValue {
-
-    void setObject(boolean reverse, IntsRef ref, IndexBased value);
-
-    IndexBased getObject(boolean reverse, IntsRef ref);
-}
diff --git a/core/src/main/java/com/graphhopper/routing/profiles/RoadClass.java b/core/src/main/java/com/graphhopper/routing/profiles/RoadClass.java
index bba058d60..64536902b 100644
--- a/core/src/main/java/com/graphhopper/routing/profiles/RoadClass.java
+++ b/core/src/main/java/com/graphhopper/routing/profiles/RoadClass.java
@@ -1,55 +1,21 @@
 package com.graphhopper.routing.profiles;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class RoadClass implements IndexBased {
-    private static final List<RoadClass> values = create("_default",
-            "motorway", "motorway_link", "motorroad",
-            "trunk", "trunk_link",
-            "primary", "primary_link",
-            "secondary", "secondary_link",
-            "tertiary", "tertiary_link",
-            "residential", "unclassified",
-            "service", "road", "track", "forestry", "steps", "cycleway", "path", "living_street");
+public enum RoadClass {
+    OTHER("other"), MOTORWAY("motorway"), MOTORROAD("motorroad"),
+    TRUNK("trunk"), PRIMARY("primary"), SECONDARY("secondary"),
+    TERTIARY("tertiary"), RESIDENTIAL("residential"), UNCLASSIFIED("unclassified"),
+    SERVICE("service"), ROAD("road"), TRACK("track"),
+    FORESTRY("forestry"), STEPS("steps"), CYCLEWAY("cycleway"),
+    PATH("path"), LIVING_STREET("living_street");
 
     private final String name;
-    private final int ordinal;
 
-    private RoadClass(String name, int ordinal) {
+    RoadClass(String name) {
         this.name = name;
-        this.ordinal = ordinal;
     }
 
-
     @Override
     public String toString() {
         return name;
     }
-
-    @Override
-    public int ordinal() {
-        return ordinal;
-    }
-
-    @Override
-    public int hashCode() {
-        return ordinal;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof RoadClass))
-            return false;
-        return ((RoadClass) obj).ordinal == ordinal;
-    }
-
-    public static List<RoadClass> create(String... values) {
-        List<RoadClass> list = new ArrayList<>(values.length);
-        for (int i = 0; i < values.length; i++) {
-            list.add(new RoadClass(values[i], i));
-        }
-        return Collections.unmodifiableList(list);
-    }
 }
diff --git a/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
index e1afaf9f9..4d7df3065 100644
--- a/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
@@ -605,8 +605,8 @@ public abstract class AbstractFlagEncoder implements FlagEncoder {
     }
 
     @Override
-    public ObjectEncodedValue getObjectEncodedValue(String key) {
-        return encodedValueLookup.getObjectEncodedValue(key);
+    public <T extends Enum> EnumEncodedValue getEnumEncodedValue(String key, Class<T> enumType) {
+        return encodedValueLookup.getEnumEncodedValue(key, enumType);
     }
 
     public void setEncodedValueLookup(EncodedValueLookup encodedValueLookup) {
diff --git a/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java b/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
index 0b6067de2..5959c25e5 100644
--- a/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
+++ b/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
@@ -627,8 +627,9 @@ public class EncodingManager implements EncodedValueLookup {
     }
 
     @Override
-    public ObjectEncodedValue getObjectEncodedValue(String key) {
-        return getEncodedValue(key, ObjectEncodedValue.class);
+    @SuppressWarnings("unchecked")
+    public <T extends Enum> EnumEncodedValue<T> getEnumEncodedValue(String key, Class<T> type) {
+        return (EnumEncodedValue<T>) getEncodedValue(key, EnumEncodedValue.class);
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/storage/BaseGraph.java b/core/src/main/java/com/graphhopper/storage/BaseGraph.java
index 7019cea0b..f2a938d17 100644
--- a/core/src/main/java/com/graphhopper/storage/BaseGraph.java
+++ b/core/src/main/java/com/graphhopper/storage/BaseGraph.java
@@ -1256,25 +1256,25 @@ class BaseGraph implements Graph {
         }
 
         @Override
-        public IndexBased get(ObjectEncodedValue property) {
-            return property.getObject(reverse, getFlags());
+        public <T extends Enum> T get(EnumEncodedValue<T> property) {
+            return property.getEnum(reverse, getFlags());
         }
 
         @Override
-        public EdgeIteratorState set(ObjectEncodedValue property, IndexBased value) {
-            property.setObject(reverse, getFlags(), value);
+        public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
+            property.setEnum(reverse, getFlags(), value);
             edgeAccess.writeFlags(edgePointer, getFlags());
             return this;
         }
 
         @Override
-        public IndexBased getReverse(ObjectEncodedValue property) {
-            return property.getObject(!reverse, getFlags());
+        public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
+            return property.getEnum(!reverse, getFlags());
         }
 
         @Override
-        public EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value) {
-            property.setObject(!reverse, getFlags(), value);
+        public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
+            property.setEnum(!reverse, getFlags(), value);
             edgeAccess.writeFlags(edgePointer, getFlags());
             return this;
         }
diff --git a/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java b/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java
index b041e62b3..1fd0b0d6c 100644
--- a/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java
+++ b/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java
@@ -89,7 +89,7 @@ public interface EdgeIteratorState {
     int getAdjNode();
 
     /**
-     * For roadnetwork data like OSM a way is nearly always a curve not just a straight line. These
+     * For road network data like OSM a way is nearly always a curve not just a straight line. These
      * nodes are called pillar nodes and are between tower nodes (which are used for routing), they
      * are necessary to have a more exact geometry. See the docs for more information
      * (docs/core/low-level-api.md#what-are-pillar-and-tower-nodes). Updates to the returned list
@@ -161,13 +161,13 @@ public interface EdgeIteratorState {
 
     EdgeIteratorState setReverse(DecimalEncodedValue property, double value);
 
-    IndexBased get(ObjectEncodedValue property);
+    <T extends Enum> T get(EnumEncodedValue<T> property);
 
-    EdgeIteratorState set(ObjectEncodedValue property, IndexBased value);
+    <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value);
 
-    IndexBased getReverse(ObjectEncodedValue property);
+    <T extends Enum> T getReverse(EnumEncodedValue<T> property);
 
-    EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value);
+    <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value);
 
     String getName();
 
diff --git a/core/src/main/java/com/graphhopper/util/GHUtility.java b/core/src/main/java/com/graphhopper/util/GHUtility.java
index 903374b17..e4596d1b9 100644
--- a/core/src/main/java/com/graphhopper/util/GHUtility.java
+++ b/core/src/main/java/com/graphhopper/util/GHUtility.java
@@ -21,11 +21,10 @@ import com.carrotsearch.hppc.IntIndexedContainer;
 import com.graphhopper.coll.GHBitSet;
 import com.graphhopper.coll.GHBitSetImpl;
 import com.graphhopper.coll.GHIntArrayList;
-import com.graphhopper.routing.profiles.*;
-import com.graphhopper.routing.util.AllCHEdgesIterator;
-import com.graphhopper.routing.util.AllEdgesIterator;
-import com.graphhopper.routing.util.EdgeFilter;
-import com.graphhopper.routing.util.FlagEncoder;
+import com.graphhopper.routing.profiles.BooleanEncodedValue;
+import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EnumEncodedValue;
+import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.routing.util.*;
 import com.graphhopper.storage.*;
 import com.graphhopper.util.shapes.BBox;
@@ -43,6 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  */
 public class GHUtility {
     private static final Logger LOGGER = LoggerFactory.getLogger(GHUtility.class);
+
     /**
      * This method could throw an exception if problems like index out of bounds etc
      */
@@ -671,22 +671,22 @@ public class GHUtility {
         }
 
         @Override
-        public IndexBased get(ObjectEncodedValue property) {
+        public <T extends Enum> T get(EnumEncodedValue<T> property) {
             throw new UnsupportedOperationException("Not supported. Edge is empty.");
         }
 
         @Override
-        public EdgeIteratorState set(ObjectEncodedValue property, IndexBased value) {
+        public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
             throw new UnsupportedOperationException("Not supported. Edge is empty.");
         }
 
         @Override
-        public IndexBased getReverse(ObjectEncodedValue property) {
+        public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
             throw new UnsupportedOperationException("Not supported. Edge is empty.");
         }
 
         @Override
-        public EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value) {
+        public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
             throw new UnsupportedOperationException("Not supported. Edge is empty.");
         }
 
diff --git a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/GraphSupport.java b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/GraphSupport.java
index 03c7ab090..53b85c0ed 100644
--- a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/GraphSupport.java
+++ b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/GraphSupport.java
@@ -18,7 +18,10 @@
 
 package com.graphhopper.reader.gtfs;
 
-import com.graphhopper.routing.profiles.*;
+import com.graphhopper.routing.profiles.BooleanEncodedValue;
+import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EnumEncodedValue;
+import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.routing.util.AllEdgesIterator;
 import com.graphhopper.routing.util.EdgeFilter;
 import com.graphhopper.storage.*;
@@ -257,23 +260,23 @@ class GraphSupport {
                     }
 
                     @Override
-                    public IndexBased get(ObjectEncodedValue property) {
+                    public <T extends Enum> T get(EnumEncodedValue<T> property) {
                         return edge.get(property);
                     }
 
                     @Override
-                    public EdgeIteratorState set(ObjectEncodedValue property, IndexBased value) {
+                    public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
                         edge.set(property, value);
                         return this;
                     }
 
                     @Override
-                    public IndexBased getReverse(ObjectEncodedValue property) {
+                    public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
                         return edge.getReverse(property);
                     }
 
                     @Override
-                    public EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value) {
+                    public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
                         edge.setReverse(property, value);
                         return this;
                     }
diff --git a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java
index 38f5bd27e..032292df9 100644
--- a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java
+++ b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java
@@ -19,7 +19,10 @@
 package com.graphhopper.reader.gtfs;
 
 import com.graphhopper.routing.VirtualEdgeIteratorState;
-import com.graphhopper.routing.profiles.*;
+import com.graphhopper.routing.profiles.BooleanEncodedValue;
+import com.graphhopper.routing.profiles.DecimalEncodedValue;
+import com.graphhopper.routing.profiles.EnumEncodedValue;
+import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.routing.util.AllEdgesIterator;
 import com.graphhopper.routing.util.EdgeFilter;
 import com.graphhopper.storage.Graph;
@@ -95,7 +98,7 @@ public class WrapperGraph implements Graph {
                 return IntStream.concat(
                         IntStream.of(baseGraph.getAllEdges().length() - 1),
                         extraEdges.stream().mapToInt(VirtualEdgeIteratorState::getEdge))
-                        .max().getAsInt()+1;
+                        .max().getAsInt() + 1;
             }
 
             @Override
@@ -229,22 +232,22 @@ public class WrapperGraph implements Graph {
             }
 
             @Override
-            public IndexBased get(ObjectEncodedValue property) {
+            public <T extends Enum> T get(EnumEncodedValue<T> property) {
                 throw new UnsupportedOperationException();
             }
 
             @Override
-            public IndexBased getReverse(ObjectEncodedValue property) {
+            public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
                 throw new UnsupportedOperationException();
             }
 
             @Override
-            public EdgeIteratorState set(ObjectEncodedValue property, IndexBased value) {
+            public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
                 throw new UnsupportedOperationException();
             }
 
             @Override
-            public EdgeIteratorState setReverse(ObjectEncodedValue property, IndexBased value) {
+            public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
                 throw new UnsupportedOperationException();
             }
 


Test patch:
diff --git a/core/src/test/java/com/graphhopper/routing/profiles/EnumEncodedValueTest.java b/core/src/test/java/com/graphhopper/routing/profiles/EnumEncodedValueTest.java
new file mode 100644
index 000000000..f3c18da93
--- /dev/null
+++ b/core/src/test/java/com/graphhopper/routing/profiles/EnumEncodedValueTest.java
@@ -0,0 +1,26 @@
+package com.graphhopper.routing.profiles;
+
+import com.graphhopper.storage.IntsRef;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class EnumEncodedValueTest {
+
+    @Test
+    public void testInit() {
+        EnumEncodedValue<RoadClass> prop = new EnumEncodedValue<>("road_class", RoadClass.class);
+        EncodedValue.InitializerConfig init = new EncodedValue.InitializerConfig();
+        assertEquals(5, prop.init(init));
+        assertEquals(5, prop.bits);
+        assertEquals(0, init.dataIndex);
+        assertEquals(0, init.shift);
+        IntsRef ref = new IntsRef(1);
+        // default if empty
+        ref.ints[0] = 0;
+        assertEquals(RoadClass.OTHER, prop.getEnum(false, ref));
+
+        prop.setEnum(false, ref, RoadClass.SECONDARY);
+        assertEquals(RoadClass.SECONDARY, prop.getEnum(false, ref));
+    }
+}
\ No newline at end of file
diff --git a/core/src/test/java/com/graphhopper/routing/profiles/MappedObjectEncodedValueTest.java b/core/src/test/java/com/graphhopper/routing/profiles/MappedObjectEncodedValueTest.java
deleted file mode 100644
index fc835f885..000000000
--- a/core/src/test/java/com/graphhopper/routing/profiles/MappedObjectEncodedValueTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.graphhopper.routing.profiles;
-
-import com.graphhopper.storage.IntsRef;
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class MappedObjectEncodedValueTest {
-
-    @Test
-    public void testInit() {
-        List<RoadClass> list = RoadClass.create("primary", "secondary");
-        RoadClass primary = list.get(0);
-        RoadClass secondary = list.get(1);
-        MappedObjectEncodedValue prop = new MappedObjectEncodedValue("road_class", list);
-        EncodedValue.InitializerConfig init = new EncodedValue.InitializerConfig();
-        assertEquals(2, prop.init(init));
-        assertEquals(2, prop.bits);
-        assertEquals(0, init.dataIndex);
-        assertEquals(0, init.shift);
-        IntsRef ref = new IntsRef(1);
-        // default if empty
-        ref.ints[0] = 0;
-        assertEquals(primary, prop.getObject(false, ref));
-
-        prop.setObject(false, ref, secondary);
-        assertEquals(secondary, prop.getObject(false, ref));
-    }
-}
\ No newline at end of file