Repository: graphhopper/graphhopper
Pull request #1805 (2019-11-26 16:59:41)

introduce required encoded values
This PR basically moves all the current intermediate code into the build method making the EncodingManager.Builder a real builder. It is no longer required to know the order in which the different parsers should be added.

And it adds some EncodedValues if not yet existing. This will make it easier to handle instruction calculation like #990. Certainly some EncodedValues should still stay optional but having road_class and max_speed is important for calculating the instructions of all different travel modes. 

This PR also removes the no longer necessary method GHUtility.addDefaultEncodedValues. 

Now, if elevation is enabled the elevation interpolation is done without further configuration, ie. some tests needed minor changes.


Patch:
diff --git a/core/files/changelog.txt b/core/files/changelog.txt
index 0ce00f80c..632defa64 100644
--- a/core/files/changelog.txt
+++ b/core/files/changelog.txt
@@ -1,4 +1,5 @@
 1.0
+    add required EncodedValues like road_class to EncodingManager if not added from user
     removed PathNative,PathBidirRef,Path4CH,EdgeBasedPathCH and moved path extraction code out of Path class, added PathExtractor,BidirPathExtractor(+subclasses for CH) instead, #1730
     conditional turn restrictions now supported, #1683
     added new `curbside` feature, #1697
diff --git a/core/src/main/java/com/graphhopper/routing/util/DataFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/DataFlagEncoder.java
index a5c1f2ffd..7a4182022 100644
--- a/core/src/main/java/com/graphhopper/routing/util/DataFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/DataFlagEncoder.java
@@ -91,13 +91,6 @@ public class DataFlagEncoder extends AbstractFlagEncoder {
         // TODO support different vehicle types, currently just roundabout and fwd&bwd for one vehicle type
         super.createEncodedValues(registerNewEncodedValue, prefix, index);
 
-        for (String key : Arrays.asList(RoadClass.KEY, RoadEnvironment.KEY, RoadAccess.KEY, MaxSpeed.KEY)) {
-            if (!encodedValueLookup.hasEncodedValue(key))
-                throw new IllegalStateException("To use DataFlagEncoder and the GenericWeighting you need to add " +
-                        "the encoded value " + key + " before this '" + toString() + "' flag encoder. Order is important! " +
-                        "E.g. use the config: graph.encoded_values: " + key);
-        }
-
         // workaround to init AbstractWeighting.avSpeedEnc variable that GenericWeighting does not need
         avgSpeedEnc = new UnsignedDecimalEncodedValue("fake", 1, 1, false);
         roadEnvironmentEnc = getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
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 56aae8779..5819b9c05 100644
--- a/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
+++ b/core/src/main/java/com/graphhopper/routing/util/EncodingManager.java
@@ -108,7 +108,7 @@ public class EncodingManager implements EncodedValueLookup {
             throw new IllegalStateException("Cannot load properties to fetch EncodingManager configuration at: "
                     + dir.getLocation());
 
-        EncodingManager.Builder builder = new EncodingManager.Builder(false);
+        EncodingManager.Builder builder = new EncodingManager.Builder();
         String encodedValuesStr = properties.get("graph.encoded_values");
         if (!Helper.isEmpty(encodedValuesStr))
             builder.addAll(evFactory, encodedValuesStr);
@@ -144,15 +144,14 @@ public class EncodingManager implements EncodedValueLookup {
 
     public static class Builder {
         private EncodingManager em;
+        List<AbstractFlagEncoder> flagEncoderList = new ArrayList<>();
+        List<EncodedValue> encodedValueList = new ArrayList<>();
+        List<TagParser> tagParsers = new ArrayList<>();
+        List<TurnCostParser> turnCostParsers = new ArrayList<>();
+        List<RelationTagParser> relationTagParsers = new ArrayList<>();
 
         public Builder() {
-            this(true);
-        }
-
-        private Builder(boolean addRoundabout) {
             em = new EncodingManager();
-            if (addRoundabout)
-                add(new OSMRoundaboutParser());
         }
 
         /**
@@ -186,67 +185,46 @@ public class EncodingManager implements EncodedValueLookup {
          * For backward compatibility provide a way to add multiple FlagEncoders
          */
         public Builder addAll(FlagEncoderFactory factory, String flagEncodersStr) {
+            check();
             for (FlagEncoder fe : parseEncoderString(factory, flagEncodersStr)) {
-                add(fe);
+                flagEncoderList.add((AbstractFlagEncoder) fe);
             }
             return this;
         }
 
         public Builder addAll(EncodedValueFactory factory, String encodedValueString) {
-            em.add(this, factory, encodedValueString);
+            check();
+            em.add(encodedValueList, factory, encodedValueString);
             return this;
         }
 
         public Builder addAll(TagParserFactory factory, String tagParserString) {
-            em.add(this, factory, tagParserString);
+            check();
+            em.add(tagParsers, factory, tagParserString);
             return this;
         }
 
         public Builder addTurnCostParser(TurnCostParser parser) {
-            List<EncodedValue> list = new ArrayList<>();
-            parser.createTurnCostEncodedValues(em, list);
-            for (EncodedValue ev : list) {
-                ev.init(em.turnCostConfig);
-                if (em.encodedValueMap.containsKey(ev.getName()))
-                    throw new IllegalArgumentException("Already defined: " + ev.getName() + ". Please note that " +
-                            "EncodedValues for edges and turn cost are in the same namespace.");
-                em.encodedValueMap.put(ev.getName(), ev);
-            }
-            em.turnCostParsers.put(parser.getName(), parser);
+            check();
+            turnCostParsers.add(parser);
             return this;
         }
 
         public Builder addRelationTagParser(RelationTagParser tagParser) {
-            List<EncodedValue> list = new ArrayList<>();
-            tagParser.createRelationEncodedValues(em, list);
-            for (EncodedValue ev : list) {
-                ev.init(em.relationConfig);
-            }
-            em.relationTagParsers.add(tagParser);
-
-            // add as "edge" TagParser
-            add(tagParser, true);
+            check();
+            relationTagParsers.add(tagParser);
             return this;
         }
 
         public Builder add(FlagEncoder encoder) {
             check();
-            if (encoder instanceof BikeCommonFlagEncoder && !em.hasEncodedValue(getKey("bike", RouteNetwork.EV_SUFFIX))) {
-                addRelationTagParser(new OSMBikeNetworkTagParser());
-            } else if (encoder instanceof FootFlagEncoder && !em.hasEncodedValue(getKey("foot", RouteNetwork.EV_SUFFIX))) {
-                addRelationTagParser(new OSMFootNetworkTagParser());
-            }
-
-            em.addEncoder((AbstractFlagEncoder) encoder);
+            flagEncoderList.add((AbstractFlagEncoder) encoder);
             return this;
         }
 
         public Builder add(EncodedValue encodedValue) {
             check();
-            if (!em.edgeEncoders.isEmpty())
-                throw new IllegalArgumentException("Always add shared EncodedValues before FlagEncoders to ensure they can be loaded first");
-
-            em.addEncodedValue(encodedValue, false);
+            encodedValueList.add(encodedValue);
             return this;
         }
 
@@ -255,34 +233,115 @@ public class EncodingManager implements EncodedValueLookup {
          * createEncodedValues.
          */
         public Builder add(TagParser tagParser) {
-            return add(tagParser, false);
+            check();
+            tagParsers.add(tagParser);
+            return this;
         }
 
-        private Builder add(TagParser tagParser, boolean encValBoundToFlagEncoder) {
+        private void check() {
+            if (em == null)
+                throw new IllegalStateException("Cannot call method after Builder.build() was called");
+        }
+
+        private void _addEdgeTagParser(TagParser tagParser, boolean withNamespace, boolean insert) {
             List<EncodedValue> list = new ArrayList<>();
             tagParser.createEncodedValues(em, list);
             for (EncodedValue ev : list) {
-                em.addEncodedValue(ev, encValBoundToFlagEncoder);
+                em.addEncodedValue(ev, withNamespace);
             }
-            em.edgeTagParsers.add(tagParser);
-            return this;
+            if (insert)
+                em.edgeTagParsers.add(0, tagParser);
+            else
+                em.edgeTagParsers.add(tagParser);
         }
 
-        private void check() {
-            if (em == null)
-                throw new IllegalStateException("Cannot call method after Builder.build() was called");
+        private void _addRelationTagParser(RelationTagParser tagParser) {
+            List<EncodedValue> list = new ArrayList<>();
+            tagParser.createRelationEncodedValues(em, list);
+            for (EncodedValue ev : list) {
+                ev.init(em.relationConfig);
+            }
+            em.relationTagParsers.add(tagParser);
+
+            // for simplicity add into edge-EncodedValue
+            _addEdgeTagParser(tagParser, true, false);
+        }
+
+        private void _addTurnCostParser(TurnCostParser parser) {
+            List<EncodedValue> list = new ArrayList<>();
+            parser.createTurnCostEncodedValues(em, list);
+            for (EncodedValue ev : list) {
+                ev.init(em.turnCostConfig);
+                if (em.encodedValueMap.containsKey(ev.getName()))
+                    throw new IllegalArgumentException("Already defined: " + ev.getName() + ". Please note that " +
+                            "EncodedValues for edges and turn cost are in the same namespace.");
+                em.encodedValueMap.put(ev.getName(), ev);
+            }
+            em.turnCostParsers.put(parser.getName(), parser);
         }
 
         public EncodingManager build() {
             check();
-            if (em.encodedValueMap.isEmpty())
-                throw new IllegalStateException("No EncodedValues found");
 
-            for (AbstractFlagEncoder encoder : em.edgeEncoders) {
+            for (RelationTagParser tagParser : relationTagParsers) {
+                _addRelationTagParser(tagParser);
+            }
+
+            List<SpatialRuleParser> insertLater = new ArrayList<>();
+            for (TagParser tagParser : tagParsers) {
+                if (SpatialRuleParser.class.isAssignableFrom(tagParser.getClass())) {
+                    insertLater.add((SpatialRuleParser) tagParser);
+                } else {
+                    _addEdgeTagParser(tagParser, false, false);
+                }
+            }
+
+            for (EncodedValue ev : encodedValueList) {
+                em.addEncodedValue(ev, false);
+            }
+
+            if (!em.encodedValueMap.containsKey(RoadAccess.KEY))
+                _addEdgeTagParser(new OSMRoadAccessParser(), false, true);
+            if (!em.encodedValueMap.containsKey(MaxSpeed.KEY))
+                _addEdgeTagParser(new OSMMaxSpeedParser(), false, true);
+            if (!em.encodedValueMap.containsKey(RoadEnvironment.KEY))
+                _addEdgeTagParser(new OSMRoadEnvironmentParser(), false, true);
+            if (!em.encodedValueMap.containsKey(RoadClassLink.KEY))
+                _addEdgeTagParser(new OSMRoadClassLinkParser(), false, true);
+            if (!em.encodedValueMap.containsKey(RoadClass.KEY))
+                _addEdgeTagParser(new OSMRoadClassParser(), false, true);
+            if (!em.encodedValueMap.containsKey(Roundabout.KEY))
+                _addEdgeTagParser(new OSMRoundaboutParser(), false, true);
+
+            // TODO can we avoid this hack without complex dependency management?
+            // ensure that SpatialRuleParser come after required EncodedValues like max_speed or road_access
+            for (SpatialRuleParser srp : insertLater) {
+                _addEdgeTagParser(srp, false, true);
+            }
+
+            for (AbstractFlagEncoder encoder : flagEncoderList) {
+                if (encoder instanceof BikeCommonFlagEncoder && !em.hasEncodedValue(getKey("bike", RouteNetwork.EV_SUFFIX))) {
+                    _addRelationTagParser(new OSMBikeNetworkTagParser());
+                } else if (encoder instanceof FootFlagEncoder && !em.hasEncodedValue(getKey("foot", RouteNetwork.EV_SUFFIX))) {
+                    _addRelationTagParser(new OSMFootNetworkTagParser());
+                }
+
+                em.addEncoder(encoder);
+            }
+
+            for (TurnCostParser parser : turnCostParsers) {
+                _addTurnCostParser(parser);
+            }
+
+            // FlagEncoder can demand TurnCostParsers => add them after the explicitly added ones
+            for (AbstractFlagEncoder encoder : flagEncoderList) {
                 if (encoder.supports(TurnWeighting.class) && !em.turnCostParsers.containsKey(encoder.toString()))
-                    addTurnCostParser(new OSMTurnRelationParser(encoder.toString(), encoder.getMaxTurnCosts()));
+                    _addTurnCostParser(new OSMTurnRelationParser(encoder.toString(), encoder.getMaxTurnCosts()));
             }
 
+            if (em.encodedValueMap.isEmpty())
+                throw new IllegalStateException("No EncodedValues found");
+
             EncodingManager tmp = em;
             em = null;
             return tmp;
@@ -315,7 +374,7 @@ public class EncodingManager implements EncodedValueLookup {
         return resultEncoders;
     }
 
-    private void add(Builder builder, EncodedValueFactory factory, String evList) {
+    private void add(List<EncodedValue> returnList, EncodedValueFactory factory, String evList) {
         if (!evList.equals(toLowerCase(evList)))
             throw new IllegalArgumentException("Use lower case for EncodedValues: " + evList);
 
@@ -325,14 +384,14 @@ public class EncodingManager implements EncodedValueLookup {
                 continue;
 
             EncodedValue evObject = factory.create(entry);
-            builder.add(evObject);
             PMap map = new PMap(entry);
             if (!map.has("version"))
                 throw new IllegalArgumentException("encoded value must have a version specified but it was " + entry);
+            returnList.add(evObject);
         }
     }
 
-    private void add(Builder builder, TagParserFactory factory, String tpList) {
+    private void add(List<TagParser> returnList, TagParserFactory factory, String tpList) {
         if (!tpList.equals(toLowerCase(tpList)))
             throw new IllegalArgumentException("Use lower case for TagParser: " + tpList);
 
@@ -343,7 +402,7 @@ public class EncodingManager implements EncodedValueLookup {
 
             PMap map = new PMap(entry);
             TagParser tp = factory.create(entry, map);
-            builder.add(tp);
+            returnList.add(tp);
         }
     }
 
@@ -398,13 +457,13 @@ public class EncodingManager implements EncodedValueLookup {
         edgeEncoders.add(encoder);
     }
 
-    private void addEncodedValue(EncodedValue ev, boolean encValBoundToFlagEncoder) {
+    private void addEncodedValue(EncodedValue ev, boolean withNamespace) {
         if (encodedValueMap.containsKey(ev.getName()))
             throw new IllegalStateException("EncodedValue " + ev.getName() + " already exists " + encodedValueMap.get(ev.getName()) + " vs " + ev);
-        if (!encValBoundToFlagEncoder && ev.getName().contains(SPECIAL_SEPARATOR))
-            throw new IllegalArgumentException("EncodedValue " + ev.getName() + " must not contain '" + SPECIAL_SEPARATOR + "'");
-        if (encValBoundToFlagEncoder && !ev.getName().contains(SPECIAL_SEPARATOR))
-            throw new IllegalArgumentException("EncodedValue " + ev.getName() + " must contain '" + SPECIAL_SEPARATOR + "' as reserved for a single profile");
+        if (!withNamespace && ev.getName().contains(SPECIAL_SEPARATOR))
+            throw new IllegalArgumentException("EncodedValue " + ev.getName() + " must not contain namespace character '" + SPECIAL_SEPARATOR + "'");
+        if (withNamespace && !ev.getName().contains(SPECIAL_SEPARATOR))
+            throw new IllegalArgumentException("EncodedValue " + ev.getName() + " must contain namespace character '" + SPECIAL_SEPARATOR + "'");
         ev.init(edgeConfig);
         encodedValueMap.put(ev.getName(), ev);
     }
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java
index c787c00a5..ff991d7e2 100644
--- a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMTurnRelationParser.java
@@ -79,8 +79,6 @@ public class OSMTurnRelationParser implements TurnCostParser {
     @Override
     public void createTurnCostEncodedValues(EncodedValueLookup lookup, List<EncodedValue> registerNewEncodedValue) {
         String accessKey = getKey(name, "access");
-        if (!lookup.hasEncodedValue(accessKey))
-            throw new IllegalArgumentException("Add TurnCostParsers to EncodingManager after everything else");
         accessEnc = lookup.getEncodedValue(accessKey, BooleanEncodedValue.class);
         registerNewEncodedValue.add(turnCostEnc = TurnCost.create(name, maxTurnCosts));
     }
@@ -97,7 +95,7 @@ public class OSMTurnRelationParser implements TurnCostParser {
         return cachedInExplorer == null ? cachedInExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.inEdges(accessEnc)) : cachedInExplorer;
     }
 
-    EdgeExplorer getOutExplorer(Graph graph) {
+    private EdgeExplorer getOutExplorer(Graph graph) {
         return cachedOutExplorer == null ? cachedOutExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.outEdges(accessEnc)) : cachedOutExplorer;
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/SpatialRuleParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/SpatialRuleParser.java
index 9d9cd592c..32896238c 100644
--- a/core/src/main/java/com/graphhopper/routing/util/parsers/SpatialRuleParser.java
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/SpatialRuleParser.java
@@ -27,6 +27,9 @@ import com.graphhopper.util.shapes.GHPoint;
 
 import java.util.List;
 
+/**
+ * This parser stores the spatialId in the edgeFlags based on previously defined areas.
+ */
 public class SpatialRuleParser implements TagParser {
 
     private final IntEncodedValue spatialRuleEnc;
diff --git a/core/src/main/java/com/graphhopper/util/GHUtility.java b/core/src/main/java/com/graphhopper/util/GHUtility.java
index cb4074e2d..5a969cf92 100644
--- a/core/src/main/java/com/graphhopper/util/GHUtility.java
+++ b/core/src/main/java/com/graphhopper/util/GHUtility.java
@@ -631,12 +631,6 @@ public class GHUtility {
         return edge;
     }
 
-    public static EncodingManager.Builder addDefaultEncodedValues(EncodingManager.Builder builder) {
-        return builder.add(new OSMRoadClassParser()).add(new OSMRoadClassLinkParser()).
-                add(new OSMRoadEnvironmentParser()).add(new OSMMaxSpeedParser()).add(new OSMRoadAccessParser()).
-                add(new OSMSurfaceParser());
-    }
-
     public static void updateDistancesFor(Graph g, int node, double lat, double lon) {
         NodeAccess na = g.getNodeAccess();
         na.setNode(node, lat, lon);


Test patch:
diff --git a/core/src/test/java/com/graphhopper/GraphHopperAPITest.java b/core/src/test/java/com/graphhopper/GraphHopperAPITest.java
index ca7b38c21..87b9f4489 100644
--- a/core/src/test/java/com/graphhopper/GraphHopperAPITest.java
+++ b/core/src/test/java/com/graphhopper/GraphHopperAPITest.java
@@ -115,7 +115,7 @@ public class GraphHopperAPITest {
     public void testDoNotInterpolateTwice1645() {
         String loc = "./target/issue1645";
         Helper.removeDir(new File(loc));
-        EncodingManager em = new EncodingManager.Builder().add(new OSMRoadEnvironmentParser()).add(new CarFlagEncoder()).build();
+        EncodingManager em = new EncodingManager.Builder().add(new CarFlagEncoder()).build();
         GraphHopperStorage graph = GraphBuilder.start(em).setRAM(loc, true).set3D(true).create();
 
         // we need elevation
diff --git a/core/src/test/java/com/graphhopper/reader/dem/EdgeElevationInterpolatorTest.java b/core/src/test/java/com/graphhopper/reader/dem/EdgeElevationInterpolatorTest.java
index 7c0ff589b..be665fb67 100644
--- a/core/src/test/java/com/graphhopper/reader/dem/EdgeElevationInterpolatorTest.java
+++ b/core/src/test/java/com/graphhopper/reader/dem/EdgeElevationInterpolatorTest.java
@@ -55,8 +55,7 @@ public abstract class EdgeElevationInterpolatorTest {
     @Before
     public void setUp() {
         graph = new GraphHopperStorage(new RAMDirectory(),
-                encodingManager = new EncodingManager.Builder().add(new CarFlagEncoder()).add(new FootFlagEncoder()).
-                        add(new OSMRoadEnvironmentParser()).build(),
+                encodingManager = new EncodingManager.Builder().add(new CarFlagEncoder()).add(new FootFlagEncoder()).build(),
                 true).create(100);
         roadEnvEnc = encodingManager.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
         edgeElevationInterpolator = createEdgeElevationInterpolator();
diff --git a/core/src/test/java/com/graphhopper/routing/PathTest.java b/core/src/test/java/com/graphhopper/routing/PathTest.java
index abfcb13b8..83d5402e7 100644
--- a/core/src/test/java/com/graphhopper/routing/PathTest.java
+++ b/core/src/test/java/com/graphhopper/routing/PathTest.java
@@ -49,7 +49,7 @@ public class PathTest {
     private final BooleanEncodedValue carManagerRoundabout = carManager.getBooleanEncodedValue(Roundabout.KEY);
     private final BooleanEncodedValue carAccessEnc = encoder.getAccessEnc();
     private final DecimalEncodedValue carAvSpeedEnv = encoder.getAverageSpeedEnc();
-    private final EncodingManager dataFlagManager = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).add(dataFlagEncoder).build();
+    private final EncodingManager dataFlagManager = new EncodingManager.Builder().add(dataFlagEncoder).build();
     private final IntsRef edgeFlags = dataFlagManager.createEdgeFlags();
     private final EncodingManager mixedEncoders = EncodingManager.create(new CarFlagEncoder(), new FootFlagEncoder());
     private final BooleanEncodedValue mixedManagerRoundabout = mixedEncoders.getBooleanEncodedValue(Roundabout.KEY);
diff --git a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
index 53759cdf2..ccd8bd69b 100644
--- a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
@@ -44,7 +44,6 @@ import static org.junit.Assert.*;
 public class CarFlagEncoderTest {
     final CarFlagEncoder encoder = createEncoder();
     private final EncodingManager em = new EncodingManager.Builder().
-            add(new OSMRoadAccessParser()).
             add(encoder).
             add(new BikeFlagEncoder()).add(new FootFlagEncoder()).build();
 
diff --git a/core/src/test/java/com/graphhopper/routing/util/DataFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/DataFlagEncoderTest.java
index 04f30633d..82fb0e4fb 100644
--- a/core/src/test/java/com/graphhopper/routing/util/DataFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/DataFlagEncoderTest.java
@@ -2,10 +2,8 @@ package com.graphhopper.routing.util;
 
 import com.graphhopper.reader.ReaderWay;
 import com.graphhopper.routing.profiles.*;
-import com.graphhopper.routing.util.parsers.*;
-import com.graphhopper.routing.util.spatialrules.SpatialRule;
-import com.graphhopper.routing.util.spatialrules.SpatialRuleLookup;
-import com.graphhopper.routing.util.spatialrules.countries.GermanySpatialRule;
+import com.graphhopper.routing.util.parsers.OSMMaxSpeedParser;
+import com.graphhopper.routing.util.parsers.OSMSurfaceParser;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphBuilder;
 import com.graphhopper.storage.IntsRef;
@@ -13,15 +11,8 @@ import com.graphhopper.util.EdgeIteratorState;
 import com.graphhopper.util.GHUtility;
 import com.graphhopper.util.PMap;
 import com.graphhopper.util.TranslationMapTest;
-import com.graphhopper.util.shapes.BBox;
-import com.graphhopper.util.shapes.GHPoint;
-import com.graphhopper.util.shapes.Polygon;
 import org.junit.Test;
 
-import java.util.Arrays;
-import java.util.Collections;
-
-import static com.graphhopper.util.GHUtility.updateDistancesFor;
 import static org.junit.Assert.*;
 
 /**
@@ -44,9 +35,6 @@ public class DataFlagEncoderTest {
         properties = new PMap();
         encoder = new DataFlagEncoder(properties);
         encodingManager = new EncodingManager.Builder().
-                add(new OSMRoadEnvironmentParser()).
-                add(new OSMRoadClassParser()).
-                add(new OSMRoadAccessParser()).
                 add(new OSMSurfaceParser()).
                 add(new OSMMaxSpeedParser(carMaxSpeedEnc = MaxSpeed.create())).
                 add(encoder).build();
@@ -59,16 +47,11 @@ public class DataFlagEncoderTest {
         accessEnc = encoder.getAccessEnc();
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void testNoDefaultEncodedValues() {
-        EncodingManager em = EncodingManager.create(Arrays.asList(new DataFlagEncoder(properties)));
-    }
-
     @Test
     public void testSufficientEncoderBitLength() {
         try {
-            EncodingManager em = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).add(new DataFlagEncoder(properties)).build();
-            EncodingManager em1 = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).add(new DataFlagEncoder(properties)).build();
+            EncodingManager em = new EncodingManager.Builder().add(new DataFlagEncoder(properties)).build();
+            EncodingManager em1 = new EncodingManager.Builder().add(new DataFlagEncoder(properties)).build();
         } catch (Throwable t) {
             fail(t.toString());
         }
@@ -300,95 +283,4 @@ public class DataFlagEncoderTest {
         osmWay.setTag("highway", "building");
         assertTrue(encoder.getAccess(osmWay).canSkip());
     }
-
-    @Test
-    public void testSpatialId() {
-        final GermanySpatialRule germany = new GermanySpatialRule();
-        germany.setBorders(Collections.singletonList(new Polygon(new double[]{0, 0, 1, 1}, new double[]{0, 1, 1, 0})));
-
-        SpatialRuleLookup index = new SpatialRuleLookup() {
-            @Override
-            public SpatialRule lookupRule(double lat, double lon) {
-                for (Polygon polygon : germany.getBorders()) {
-                    if (polygon.contains(lat, lon)) {
-                        return germany;
-                    }
-                }
-                return SpatialRule.EMPTY;
-            }
-
-            @Override
-            public SpatialRule lookupRule(GHPoint point) {
-                return lookupRule(point.lat, point.lon);
-            }
-
-            @Override
-            public int getSpatialId(SpatialRule rule) {
-                if (germany.equals(rule)) {
-                    return 1;
-                } else {
-                    return 0;
-                }
-            }
-
-            @Override
-            public SpatialRule getSpatialRule(int spatialId) {
-                return SpatialRule.EMPTY;
-            }
-
-            @Override
-            public int size() {
-                return 2;
-            }
-
-            @Override
-            public BBox getBounds() {
-                return new BBox(-180, 180, -90, 90);
-            }
-        };
-
-        DataFlagEncoder tmpEncoder = new DataFlagEncoder(new PMap());
-        EncodingManager em = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder().add(new SpatialRuleParser(index))).add(tmpEncoder).build();
-        IntEncodedValue countrySpatialIdEnc = em.getIntEncodedValue(Country.KEY);
-        EnumEncodedValue<RoadAccess> tmpRoadAccessEnc = em.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class);
-        DecimalEncodedValue tmpCarMaxSpeedEnc = em.getDecimalEncodedValue(MaxSpeed.KEY);
-
-        Graph graph = new GraphBuilder(em).create();
-        EdgeIteratorState e1 = graph.edge(0, 1, 1, true);
-        EdgeIteratorState e2 = graph.edge(0, 2, 1, true);
-        EdgeIteratorState e3 = graph.edge(0, 3, 1, true);
-        EdgeIteratorState e4 = graph.edge(0, 4, 1, true);
-        updateDistancesFor(graph, 0, 0.00, 0.00);
-        updateDistancesFor(graph, 1, 0.01, 0.01);
-        updateDistancesFor(graph, 2, -0.01, -0.01);
-        updateDistancesFor(graph, 3, 0.01, 0.01);
-        updateDistancesFor(graph, 4, -0.01, -0.01);
-
-        ReaderWay way = new ReaderWay(27l);
-        way.setTag("highway", "track");
-        way.setTag("estimated_center", new GHPoint(0.005, 0.005));
-        e1.setFlags(em.handleWayTags(way, map, relFlags));
-        assertEquals(RoadAccess.DESTINATION, e1.get(tmpRoadAccessEnc));
-
-        ReaderWay way2 = new ReaderWay(28l);
-        way2.setTag("highway", "track");
-        way2.setTag("estimated_center", new GHPoint(-0.005, -0.005));
-        e2.setFlags(em.handleWayTags(way2, map, relFlags));
-        assertEquals(RoadAccess.YES, e2.get(tmpRoadAccessEnc));
-
-        assertEquals(index.getSpatialId(new GermanySpatialRule()), e1.get(countrySpatialIdEnc));
-        assertEquals(index.getSpatialId(SpatialRule.EMPTY), e2.get(countrySpatialIdEnc));
-
-        ReaderWay livingStreet = new ReaderWay(29l);
-        livingStreet.setTag("highway", "living_street");
-        livingStreet.setTag("estimated_center", new GHPoint(0.005, 0.005));
-        e3.setFlags(em.handleWayTags(livingStreet, map, relFlags));
-        assertEquals(5, e3.get(tmpCarMaxSpeedEnc), .1);
-
-        ReaderWay livingStreet2 = new ReaderWay(30l);
-        livingStreet2.setTag("highway", "living_street");
-        livingStreet2.setTag("estimated_center", new GHPoint(-0.005, -0.005));
-        e4.setFlags(em.handleWayTags(livingStreet2, map, relFlags));
-        assertEquals(MaxSpeed.UNSET_SPEED, e4.get(tmpCarMaxSpeedEnc), .1);
-    }
 }
diff --git a/core/src/test/java/com/graphhopper/routing/util/SnapPreventionEdgeFilterTest.java b/core/src/test/java/com/graphhopper/routing/util/SnapPreventionEdgeFilterTest.java
index ba955e45b..5a67372da 100644
--- a/core/src/test/java/com/graphhopper/routing/util/SnapPreventionEdgeFilterTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/SnapPreventionEdgeFilterTest.java
@@ -23,7 +23,7 @@ public class SnapPreventionEdgeFilterTest {
                 return true;
             }
         };
-        EncodingManager em = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).build();
+        EncodingManager em = new EncodingManager.Builder().build();
         EnumEncodedValue<RoadClass> rcEnc = em.getEnumEncodedValue(RoadClass.KEY, RoadClass.class);
         EnumEncodedValue<RoadEnvironment> reEnc = em.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
         SnapPreventionEdgeFilter filter = new SnapPreventionEdgeFilter(trueFilter, rcEnc, reEnc, Arrays.asList("motorway", "ferry"));
diff --git a/core/src/test/java/com/graphhopper/routing/util/parsers/SpatialRuleParserTest.java b/core/src/test/java/com/graphhopper/routing/util/parsers/SpatialRuleParserTest.java
new file mode 100644
index 000000000..e303e7b0c
--- /dev/null
+++ b/core/src/test/java/com/graphhopper/routing/util/parsers/SpatialRuleParserTest.java
@@ -0,0 +1,16 @@
+package com.graphhopper.routing.util.parsers;
+
+import com.graphhopper.routing.profiles.Country;
+import com.graphhopper.routing.util.EncodingManager;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertTrue;
+
+public class SpatialRuleParserTest {
+
+    @Test
+    public void testMixParserAdding() {
+        EncodingManager em = new EncodingManager.Builder().add(new SpatialRuleParser(null)).build();
+        assertTrue(em.hasEncodedValue(Country.KEY));
+    }
+}
\ No newline at end of file
diff --git a/core/src/test/java/com/graphhopper/routing/util/spatialrules/SpatialRuleLookupBuilderTest.java b/core/src/test/java/com/graphhopper/routing/util/spatialrules/SpatialRuleLookupBuilderTest.java
index 5ecc488e5..8d9f3dd52 100644
--- a/core/src/test/java/com/graphhopper/routing/util/spatialrules/SpatialRuleLookupBuilderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/spatialrules/SpatialRuleLookupBuilderTest.java
@@ -19,13 +19,28 @@ package com.graphhopper.routing.util.spatialrules;
 
 import com.graphhopper.jackson.Jackson;
 import com.graphhopper.json.geo.JsonFeatureCollection;
-import com.graphhopper.routing.profiles.RoadAccess;
+import com.graphhopper.reader.ReaderWay;
+import com.graphhopper.routing.profiles.*;
+import com.graphhopper.routing.util.CarFlagEncoder;
+import com.graphhopper.routing.util.EncodingManager;
+import com.graphhopper.routing.util.FlagEncoder;
+import com.graphhopper.routing.util.parsers.SpatialRuleParser;
+import com.graphhopper.routing.util.spatialrules.countries.GermanySpatialRule;
+import com.graphhopper.storage.Graph;
+import com.graphhopper.storage.GraphBuilder;
+import com.graphhopper.storage.IntsRef;
+import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.PMap;
 import com.graphhopper.util.shapes.BBox;
+import com.graphhopper.util.shapes.GHPoint;
+import com.graphhopper.util.shapes.Polygon;
 import org.junit.Test;
 
 import java.io.FileReader;
 import java.io.IOException;
+import java.util.Collections;
 
+import static com.graphhopper.util.GHUtility.updateDistancesFor;
 import static junit.framework.TestCase.assertFalse;
 import static junit.framework.TestCase.assertTrue;
 import static org.junit.Assert.assertEquals;
@@ -51,7 +66,7 @@ public class SpatialRuleLookupBuilderTest {
         assertEquals(RoadAccess.YES, spatialRuleLookup.lookupRule(48.864716, 2.349014).getAccess("primary", TransportationMode.MOTOR_VEHICLE, RoadAccess.YES));
 
         // Austria
-        assertEquals(RoadAccess.FORESTRY, spatialRuleLookup.lookupRule(48.204484,16.107888).getAccess("track", TransportationMode.MOTOR_VEHICLE, RoadAccess.YES));
+        assertEquals(RoadAccess.FORESTRY, spatialRuleLookup.lookupRule(48.204484, 16.107888).getAccess("track", TransportationMode.MOTOR_VEHICLE, RoadAccess.YES));
         assertEquals(RoadAccess.YES, spatialRuleLookup.lookupRule(48.210033, 16.363449).getAccess("primary", TransportationMode.MOTOR_VEHICLE, RoadAccess.YES));
         assertEquals(RoadAccess.DESTINATION, spatialRuleLookup.lookupRule(48.210033, 16.363449).getAccess("living_street", TransportationMode.MOTOR_VEHICLE, RoadAccess.YES));
     }
@@ -84,4 +99,96 @@ public class SpatialRuleLookupBuilderTest {
         assertEquals(SpatialRuleLookup.EMPTY, spatialRuleLookup);
     }
 
+
+    @Test
+    public void testSpatialId() {
+        final GermanySpatialRule germany = new GermanySpatialRule();
+        germany.setBorders(Collections.singletonList(new Polygon(new double[]{0, 0, 1, 1}, new double[]{0, 1, 1, 0})));
+
+        SpatialRuleLookup index = new SpatialRuleLookup() {
+            @Override
+            public SpatialRule lookupRule(double lat, double lon) {
+                for (Polygon polygon : germany.getBorders()) {
+                    if (polygon.contains(lat, lon)) {
+                        return germany;
+                    }
+                }
+                return SpatialRule.EMPTY;
+            }
+
+            @Override
+            public SpatialRule lookupRule(GHPoint point) {
+                return lookupRule(point.lat, point.lon);
+            }
+
+            @Override
+            public int getSpatialId(SpatialRule rule) {
+                if (germany.equals(rule)) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+
+            @Override
+            public SpatialRule getSpatialRule(int spatialId) {
+                return SpatialRule.EMPTY;
+            }
+
+            @Override
+            public int size() {
+                return 2;
+            }
+
+            @Override
+            public BBox getBounds() {
+                return new BBox(-180, 180, -90, 90);
+            }
+        };
+
+        EncodingManager em = new EncodingManager.Builder().add(new SpatialRuleParser(index)).add(new CarFlagEncoder(new PMap())).build();
+        IntEncodedValue countrySpatialIdEnc = em.getIntEncodedValue(Country.KEY);
+        EnumEncodedValue<RoadAccess> tmpRoadAccessEnc = em.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class);
+        DecimalEncodedValue tmpCarMaxSpeedEnc = em.getDecimalEncodedValue(MaxSpeed.KEY);
+
+        Graph graph = new GraphBuilder(em).create();
+        EdgeIteratorState e1 = graph.edge(0, 1, 1, true);
+        EdgeIteratorState e2 = graph.edge(0, 2, 1, true);
+        EdgeIteratorState e3 = graph.edge(0, 3, 1, true);
+        EdgeIteratorState e4 = graph.edge(0, 4, 1, true);
+        updateDistancesFor(graph, 0, 0.00, 0.00);
+        updateDistancesFor(graph, 1, 0.01, 0.01);
+        updateDistancesFor(graph, 2, -0.01, -0.01);
+        updateDistancesFor(graph, 3, 0.01, 0.01);
+        updateDistancesFor(graph, 4, -0.01, -0.01);
+
+        IntsRef relFlags = em.createRelationFlags();
+        EncodingManager.AcceptWay map = new EncodingManager.AcceptWay().put("car", EncodingManager.Access.WAY);
+        ReaderWay way = new ReaderWay(27l);
+        way.setTag("highway", "track");
+        way.setTag("estimated_center", new GHPoint(0.005, 0.005));
+        e1.setFlags(em.handleWayTags(way, map, relFlags));
+        assertEquals(RoadAccess.DESTINATION, e1.get(tmpRoadAccessEnc));
+
+        ReaderWay way2 = new ReaderWay(28l);
+        way2.setTag("highway", "track");
+        way2.setTag("estimated_center", new GHPoint(-0.005, -0.005));
+        e2.setFlags(em.handleWayTags(way2, map, relFlags));
+        assertEquals(RoadAccess.YES, e2.get(tmpRoadAccessEnc));
+
+        assertEquals(index.getSpatialId(new GermanySpatialRule()), e1.get(countrySpatialIdEnc));
+        assertEquals(index.getSpatialId(SpatialRule.EMPTY), e2.get(countrySpatialIdEnc));
+
+        ReaderWay livingStreet = new ReaderWay(29l);
+        livingStreet.setTag("highway", "living_street");
+        livingStreet.setTag("estimated_center", new GHPoint(0.005, 0.005));
+        e3.setFlags(em.handleWayTags(livingStreet, map, relFlags));
+        assertEquals(5, e3.get(tmpCarMaxSpeedEnc), .1);
+
+        ReaderWay livingStreet2 = new ReaderWay(30l);
+        livingStreet2.setTag("highway", "living_street");
+        livingStreet2.setTag("estimated_center", new GHPoint(-0.005, -0.005));
+        e4.setFlags(em.handleWayTags(livingStreet2, map, relFlags));
+        assertEquals(MaxSpeed.UNSET_SPEED, e4.get(tmpCarMaxSpeedEnc), .1);
+    }
 }
diff --git a/core/src/test/java/com/graphhopper/routing/weighting/GenericWeightingTest.java b/core/src/test/java/com/graphhopper/routing/weighting/GenericWeightingTest.java
index 01e1a5ffa..dec89867b 100644
--- a/core/src/test/java/com/graphhopper/routing/weighting/GenericWeightingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/weighting/GenericWeightingTest.java
@@ -45,7 +45,7 @@ public class GenericWeightingTest {
 
     public GenericWeightingTest() {
         encoder = new DataFlagEncoder();
-        em = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).add(new OSMMaxHeightParser()).
+        em = new EncodingManager.Builder().add(new OSMMaxHeightParser()).
                 add(encoder).build();
     }
 
@@ -85,7 +85,7 @@ public class GenericWeightingTest {
     @Test
     public void testDisabledRoadAttributes() {
         DataFlagEncoder simpleEncoder = new DataFlagEncoder();
-        EncodingManager simpleEncodingManager = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).add(simpleEncoder).build();
+        EncodingManager simpleEncodingManager = new EncodingManager.Builder().add(simpleEncoder).build();
         Graph simpleGraph = new GraphBuilder(simpleEncodingManager).create();
 
         ReaderWay way = new ReaderWay(27l);
diff --git a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageForDataFlagEncoderTest.java b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageForDataFlagEncoderTest.java
index 960fab72e..eff0a05f1 100644
--- a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageForDataFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageForDataFlagEncoderTest.java
@@ -36,7 +36,7 @@ public class GraphHopperStorageForDataFlagEncoderTest {
     public GraphHopperStorageForDataFlagEncoderTest() {
         properties = new PMap();
         encoder = new DataFlagEncoder(properties);
-        encodingManager = GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).
+        encodingManager = new EncodingManager.Builder().
                 add(new OSMMaxWidthParser()).add(new OSMMaxHeightParser()).add(new OSMMaxWeightParser()).add(encoder).build();
     }
 
diff --git a/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java b/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
index ac50c6be0..e6210200a 100644
--- a/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
+++ b/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
@@ -17,6 +17,7 @@
  */
 package com.graphhopper;
 
+import com.graphhopper.reader.ReaderWay;
 import com.graphhopper.reader.dem.SRTMProvider;
 import com.graphhopper.reader.osm.GraphHopperOSM;
 import com.graphhopper.routing.ch.CHAlgoFactoryDecorator;
@@ -24,6 +25,8 @@ import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.routing.util.DefaultFlagEncoderFactory;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.parsers.OSMMaxSpeedParser;
+import com.graphhopper.routing.util.parsers.OSMRoadEnvironmentParser;
+import com.graphhopper.storage.IntsRef;
 import com.graphhopper.util.*;
 import com.graphhopper.util.Parameters.CH;
 import com.graphhopper.util.Parameters.Landmark;
@@ -394,7 +397,7 @@ public class GraphHopperIT {
                 setOSMFile(DIR + "/north-bayreuth.osm.gz").
                 setCHEnabled(false).
                 setGraphHopperLocation(tmpGraphFile).
-                setEncodingManager(GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).addAll(new DefaultFlagEncoderFactory(), "car,generic").build());
+                setEncodingManager(new EncodingManager.Builder().addAll(new DefaultFlagEncoderFactory(), "car,generic").build());
         tmpHopper.importOrLoad();
 
         GHRequest req = new GHRequest(49.985307, 11.50628, 49.985731, 11.507465).
@@ -418,7 +421,7 @@ public class GraphHopperIT {
                 setOSMFile(DIR + "/north-bayreuth.osm.gz").
                 setCHEnabled(false).
                 setGraphHopperLocation(tmpGraphFile).
-                setEncodingManager(GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).add(new CarFlagEncoder()).build());
+                setEncodingManager(new EncodingManager.Builder().add(new CarFlagEncoder()).build());
         tmpHopper.importOrLoad();
 
         GHRequest req = new GHRequest(49.985272, 11.506151, 49.986107, 11.507202);
@@ -702,7 +705,7 @@ public class GraphHopperIT {
                 setAlgorithm(ASTAR).setVehicle(vehicle).setWeighting(weightCalcStr));
 
         PathWrapper arsp = rsp.getBest();
-        assertEquals(1626.8, arsp.getDistance(), .1);
+        assertEquals(1625.4, arsp.getDistance(), .1);
         assertEquals(54, arsp.getPoints().getSize());
         assertTrue(arsp.getPoints().is3D());
 
@@ -741,7 +744,13 @@ public class GraphHopperIT {
     public void testSRTMWithoutTunnelInterpolation() {
         GraphHopper tmpHopper = new GraphHopperOSM().setOSMFile(osmFile).setStoreOnFlush(true)
                 .setCHEnabled(false).setGraphHopperLocation(tmpGraphFile)
-                .setEncodingManager(EncodingManager.create(importVehicles));
+                .setEncodingManager(EncodingManager.start().add(new OSMRoadEnvironmentParser() {
+                    @Override
+                    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, EncodingManager.Access access, IntsRef relationFlags) {
+                        // do not change RoadEnvironment to avoid triggering tunnel interpolation - is this a valid use case after #TODONOW?
+                        return edgeFlags;
+                    }
+                }).addAll(new DefaultFlagEncoderFactory(), importVehicles).build());
 
         tmpHopper.setElevationProvider(new SRTMProvider(DIR));
         tmpHopper.importOrLoad();
@@ -767,7 +776,7 @@ public class GraphHopperIT {
     public void testSRTMWithTunnelInterpolation() {
         GraphHopper tmpHopper = new GraphHopperOSM().setOSMFile(osmFile).setStoreOnFlush(true)
                 .setCHEnabled(false).setGraphHopperLocation(tmpGraphFile)
-                .setEncodingManager(GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).addAll(new DefaultFlagEncoderFactory(), genericImportVehicles).build());
+                .setEncodingManager(new EncodingManager.Builder().addAll(new DefaultFlagEncoderFactory(), genericImportVehicles).build());
 
         tmpHopper.setElevationProvider(new SRTMProvider(DIR));
         tmpHopper.importOrLoad();
diff --git a/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java b/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
index 238ae09a8..ec84ef56b 100644
--- a/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
+++ b/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
@@ -563,7 +563,7 @@ public class OSMReaderTest {
         String fileRoadAttributes = "test-road-attributes.xml";
         GraphHopper hopper = new GraphHopperFacade(fileRoadAttributes);
         DataFlagEncoder dataFlagEncoder = new DataFlagEncoder();
-        hopper.setEncodingManager(GHUtility.addDefaultEncodedValues(new EncodingManager.Builder()).
+        hopper.setEncodingManager(new EncodingManager.Builder().
                 add(new OSMMaxWidthParser()).add(new OSMMaxHeightParser()).add(new OSMMaxWeightParser()).
                 add(dataFlagEncoder).build());
         hopper.importOrLoad();
@@ -949,7 +949,7 @@ public class OSMReaderTest {
                     throw new RuntimeException(e);
                 }
             }
-        }.setEncodingManager(new EncodingManager.Builder().add(new CarFlagEncoder()).add(new OSMRoadClassParser()).build()).
+        }.setEncodingManager(new EncodingManager.Builder().add(new CarFlagEncoder()).build()).
                 setGraphHopperLocation(dir).setCHEnabled(false).
                 importOrLoad();
 
@@ -958,9 +958,9 @@ public class OSMReaderTest {
         assertEquals(3, list.size());
         assertEquals(RoadClass.MOTORWAY.toString(), list.get(0).getValue());
 
-        response = gh.route(new GHRequest(51.2492152, 9.4317166, 52.133, 9.1).setPathDetails(Arrays.asList(RoadAccess.KEY)));
+        response = gh.route(new GHRequest(51.2492152, 9.4317166, 52.133, 9.1).setPathDetails(Arrays.asList(Toll.KEY)));
         Throwable ex = response.getErrors().get(0);
-        assertTrue(ex.getMessage(), ex.getMessage().contains("You requested the details [road_access]"));
+        assertTrue(ex.getMessage(), ex.getMessage().contains("You requested the details [toll]"));
     }
 
     class GraphHopperFacade extends GraphHopperOSM {
diff --git a/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java b/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java
index 291da30bf..3d59c5410 100644
--- a/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java
+++ b/reader-osm/src/test/java/com/graphhopper/routing/RoutingAlgorithmWithOSMIT.java
@@ -97,9 +97,9 @@ public class RoutingAlgorithmWithOSMIT {
     @Test
     public void testMonacoMotorcycle() {
         List<OneRun> list = new ArrayList<>();
-        list.add(new OneRun(43.730729, 7.42135, 43.727697, 7.419199, 2703, 119));
-        list.add(new OneRun(43.727687, 7.418737, 43.74958, 7.436566, 3749, 170));
-        list.add(new OneRun(43.728677, 7.41016, 43.739213, 7.4277, 3175, 169));
+        list.add(new OneRun(43.730729, 7.42135, 43.727697, 7.419199, 2682, 119));
+        list.add(new OneRun(43.727687, 7.418737, 43.74958, 7.436566, 3728, 170));
+        list.add(new OneRun(43.728677, 7.41016, 43.739213, 7.4277, 3168, 169));
         list.add(new OneRun(43.733802, 7.413433, 43.739662, 7.424355, 2423, 141));
         list.add(new OneRun(43.730949, 7.412338, 43.739643, 7.424542, 2253, 120));
         list.add(new OneRun(43.727592, 7.419333, 43.727712, 7.419333, 0, 1));
@@ -112,9 +112,9 @@ public class RoutingAlgorithmWithOSMIT {
     @Test
     public void testMonacoMotorcycleCurvature() {
         List<OneRun> list = new ArrayList<>();
-        list.add(new OneRun(43.730729, 7.42135, 43.727697, 7.419199, 2703, 119));
-        list.add(new OneRun(43.727687, 7.418737, 43.74958, 7.436566, 3749, 170));
-        list.add(new OneRun(43.728677, 7.41016, 43.739213, 7.4277, 3175, 169));
+        list.add(new OneRun(43.730729, 7.42135, 43.727697, 7.419199, 2681, 119));
+        list.add(new OneRun(43.727687, 7.418737, 43.74958, 7.436566, 3727, 170));
+        list.add(new OneRun(43.728677, 7.41016, 43.739213, 7.4277, 3168, 169));
         list.add(new OneRun(43.733802, 7.413433, 43.739662, 7.424355, 2423, 141));
         list.add(new OneRun(43.730949, 7.412338, 43.739643, 7.424542, 2253, 120));
         list.add(new OneRun(43.727592, 7.419333, 43.727712, 7.419333, 0, 1));
@@ -276,11 +276,11 @@ public class RoutingAlgorithmWithOSMIT {
         // most routes have same number of points as testMonaceFoot results but longer distance due to elevation difference
         List<OneRun> list = createMonacoFoot();
         list.get(0).setDistance(1, 1627);
-        list.get(2).setDistance(1, 2258);
+        list.get(2).setDistance(1, 2250);
         list.get(3).setDistance(1, 1482);
 
         // or slightly longer tour with less nodes: list.get(1).setDistance(1, 3610);
-        list.get(1).setDistance(1, 3595);
+        list.get(1).setDistance(1, 3573);
         list.get(1).setLocs(1, 149);
 
         runAlgo(testCollector, DIR + "/monaco.osm.gz", "target/monaco-gh",
@@ -304,9 +304,9 @@ public class RoutingAlgorithmWithOSMIT {
     public void testMonacoBike3D_twoSpeedsPerEdge() {
         List<OneRun> list = new ArrayList<>();
         // 1. alternative: go over steps 'Rampe Major' => 1.7km vs. around 2.7km
-        list.add(new OneRun(43.730864, 7.420771, 43.727687, 7.418737, 2710, 118));
+        list.add(new OneRun(43.730864, 7.420771, 43.727687, 7.418737, 2689, 118));
         // 2.
-        list.add(new OneRun(43.728499, 7.417907, 43.74958, 7.436566, 3777, 194));
+        list.add(new OneRun(43.728499, 7.417907, 43.74958, 7.436566, 3735, 194));
         // 3.
         list.add(new OneRun(43.728677, 7.41016, 43.739213, 7.427806, 2776, 167));
         // 4.
@@ -315,10 +315,10 @@ public class RoutingAlgorithmWithOSMIT {
         // try reverse direction
         // 1.
         list.add(new OneRun(43.727687, 7.418737, 43.730864, 7.420771, 2599, 115));
-        list.add(new OneRun(43.74958, 7.436566, 43.728499, 7.417907, 4199, 165));
-        list.add(new OneRun(43.739213, 7.427806, 43.728677, 7.41016, 3261, 177));
+        list.add(new OneRun(43.74958, 7.436566, 43.728499, 7.417907, 4180, 165));
+        list.add(new OneRun(43.739213, 7.427806, 43.728677, 7.41016, 3244, 177));
         // 4. avoid tunnel(s)!
-        list.add(new OneRun(43.739662, 7.424355, 43.733802, 7.413433, 2452, 112));
+        list.add(new OneRun(43.739662, 7.424355, 43.733802, 7.413433, 2436, 112));
         runAlgo(testCollector, DIR + "/monaco.osm.gz", "target/monaco-gh",
                 list, "bike2", true, "bike2", "fastest", true);
         assertEquals(testCollector.toString(), 0, testCollector.errors.size());