Repository: graphhopper/graphhopper
Pull request #1814 (2019-12-04 13:47:05)

more instruction annotations and bug fix


Patch:
diff --git a/api/src/main/java/com/graphhopper/util/Parameters.java b/api/src/main/java/com/graphhopper/util/Parameters.java
index 956f71459..266333831 100644
--- a/api/src/main/java/com/graphhopper/util/Parameters.java
+++ b/api/src/main/java/com/graphhopper/util/Parameters.java
@@ -153,11 +153,6 @@ public class Parameters {
          * This property name configures at start if the DISABLE parameter can have an effect.
          */
         public static final String INIT_DISABLING_ALLOWED = ROUTING_INIT_PREFIX + "ch.disabling_allowed";
-        /**
-         * The property name in HintsMap if heading should be used for CH regardless of the possible
-         * routing errors.
-         */
-        public static final String FORCE_HEADING = "ch.force_heading";
     }
 
     /**
diff --git a/core/files/changelog.txt b/core/files/changelog.txt
index 632defa64..335f6d51f 100644
--- a/core/files/changelog.txt
+++ b/core/files/changelog.txt
@@ -5,6 +5,7 @@
     added new `curbside` feature, #1697
     moved QueryGraph to new routing.querygraph package
     removed GraphExtension, #1783, renamed TurnCostExtension to TurnCostStorage
+    removed `heading`, `pass_through` and `ch.force_heading` parameters for speed mode/CH, #1763
 
 0.13
     removed docker compose file
diff --git a/core/src/main/java/com/graphhopper/GraphHopper.java b/core/src/main/java/com/graphhopper/GraphHopper.java
index e57785675..65cdd9136 100644
--- a/core/src/main/java/com/graphhopper/GraphHopper.java
+++ b/core/src/main/java/com/graphhopper/GraphHopper.java
@@ -1052,10 +1052,12 @@ public class GraphHopper implements GraphHopperAPI {
                 QueryGraph queryGraph;
 
                 if (chFactoryDecorator.isEnabled() && !disableCH) {
-                    boolean forceCHHeading = hints.getBool(CH.FORCE_HEADING, false);
-                    if (!forceCHHeading && request.hasFavoredHeading(0))
-                        throw new IllegalArgumentException("Heading is not (fully) supported for CHGraph. See issue #483");
+                    if (request.hasFavoredHeading(0))
+                        throw new IllegalArgumentException("The 'heading' parameter is currently not supported for speed mode, you need to disable speed mode with `ch.disable=true`. See issue #483");
 
+                    if (request.getHints().getBool(Routing.PASS_THROUGH, false)) {
+                        throw new IllegalArgumentException("The '" + Parameters.Routing.PASS_THROUGH + "' parameter is currently not supported for speed mode, you need to disable speed mode with `ch.disable=true`. See issue #1765");
+                    }
                     // if LM is enabled we have the LMFactory with the CH algo!
                     RoutingAlgorithmFactory chAlgoFactory = tmpAlgoFactory;
                     if (tmpAlgoFactory instanceof LMAlgoFactoryDecorator.LMRAFactory)
@@ -1252,7 +1254,7 @@ public class GraphHopper implements GraphHopperAPI {
         preparation.setMinOneWayNetworkSize(minOneWayNetworkSize);
         preparation.doWork();
         int currNodeCount = ghStorage.getNodes();
-        logger.info("edges: " + Helper.nf(ghStorage.getAllEdges().length()) + ", nodes " + Helper.nf(currNodeCount)
+        logger.info("edges: " + Helper.nf(ghStorage.getEdges()) + ", nodes " + Helper.nf(currNodeCount)
                 + ", there were " + Helper.nf(preparation.getMaxSubnetworks())
                 + " subnetworks. removed them => " + Helper.nf(prevNodeCount - currNodeCount)
                 + " less nodes");
diff --git a/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java b/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
index 1aa209920..9dbd75682 100644
--- a/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
+++ b/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
@@ -18,6 +18,7 @@
 package com.graphhopper.routing;
 
 import com.graphhopper.routing.profiles.*;
+import com.graphhopper.routing.util.BikeCommonFlagEncoder;
 import com.graphhopper.routing.util.DefaultEdgeFilter;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.weighting.Weighting;
@@ -52,6 +53,8 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
     private final EnumEncodedValue<RouteNetwork> bikeRouteEnc;
     private final EnumEncodedValue<RoadClass> roadClassEnc;
     private final EnumEncodedValue<RoadEnvironment> roadEnvEnc;
+    private final EnumEncodedValue<RoadAccess> roadAccessEnc;
+    private final EnumEncodedValue<Toll> tollEnc;
 
     /*
      * We need three points to make directions
@@ -95,13 +98,16 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
         this.accessEnc = evLookup.getBooleanEncodedValue(getKey(encoder.toString(), "access"));
         this.roundaboutEnc = evLookup.getBooleanEncodedValue(Roundabout.KEY);
 
-        // both EncodedValues are optional and only used when bike encoders are added
+        // both EncodedValues are optional; And return annotation only when instructions for bike encoder is requested
         String key = getKey("bike", RouteNetwork.EV_SUFFIX);
         this.bikeRouteEnc = evLookup.hasEncodedValue(key) ? evLookup.getEnumEncodedValue(key, RouteNetwork.class) : null;
-        this.getOffBikeEnc = evLookup.hasEncodedValue(GetOffBike.KEY) ? evLookup.getBooleanEncodedValue(GetOffBike.KEY) : null;
+        this.getOffBikeEnc = encoder instanceof BikeCommonFlagEncoder && evLookup.hasEncodedValue(GetOffBike.KEY)
+                ? evLookup.getBooleanEncodedValue(GetOffBike.KEY) : null;
+        this.tollEnc = evLookup.hasEncodedValue(Toll.KEY) ? evLookup.getEnumEncodedValue(Toll.KEY, Toll.class) : null;
 
         this.roadClassEnc = evLookup.getEnumEncodedValue(RoadClass.KEY, RoadClass.class);
         this.roadEnvEnc = evLookup.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
+        this.roadAccessEnc = evLookup.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class);
         this.nodeAccess = graph.getNodeAccess();
         this.tr = tr;
         this.ways = ways;
@@ -127,7 +133,6 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
         return ways;
     }
 
-
     @Override
     public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
         if (prevNode == -1) {
@@ -157,20 +162,39 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
         }
 
         String name = edge.getName();
-        InstructionAnnotation annotation = InstructionAnnotation.EMPTY;
+        String info = "";
+        int importance = 1;
         if (getOffBikeEnc != null) {
-            // only for bikes do
             if (edge.get(roadClassEnc) == RoadClass.CYCLEWAY
                     || bikeRouteEnc != null && edge.get(bikeRouteEnc) != RouteNetwork.OTHER) {
                 // for backward compatibility
-                annotation = new InstructionAnnotation(0, tr.tr("cycleway"));
+                importance = 0;
+                info = tr.tr("cycleway");
             } else if (edge.get(getOffBikeEnc)) {
-                annotation = new InstructionAnnotation(1, tr.tr("off_bike"));
+                info = tr.tr("off_bike");
             }
-        } else if (edge.get(roadEnvEnc) == RoadEnvironment.FORD) {
-            annotation = new InstructionAnnotation(1, tr.tr("way_contains_ford"));
         }
 
+        RoadEnvironment re = edge.get(roadEnvEnc);
+        if (re == RoadEnvironment.FORD) {
+            importance = 2; // could be dangerous
+            info = tr.tr("way_contains_ford");
+        } else if (re == RoadEnvironment.FERRY) {
+            info = tr.tr("way_contains_ferry");
+        }
+
+        // if private access is allowed we need a warning
+        RoadAccess ra = edge.get(roadAccessEnc);
+        if (ra == RoadAccess.PRIVATE)
+            info = info.isEmpty() ? tr.tr("way_contains_private") : info + ", " + tr.tr("way_contains_private");
+
+        if (tollEnc != null && edge.get(tollEnc) != Toll.NO)
+            info = info.isEmpty() ? tr.tr("way_contains_toll") : info + ", " + tr.tr("way_contains_toll");
+
+        InstructionAnnotation annotation = info.isEmpty()
+                ? InstructionAnnotation.EMPTY
+                : new InstructionAnnotation(importance, info);
+
         if ((prevName == null) && (!isRoundabout)) // very first instruction (if not in Roundabout)
         {
             int sign = Instruction.CONTINUE_ON_STREET;
diff --git a/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java
index 797fa54aa..4a56bd379 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedNodeContractor.java
@@ -43,7 +43,7 @@ import static com.graphhopper.util.Helper.nf;
  * <p>
  * This class is mostly concerned with triggering the required local searches and introducing the necessary shortcuts
  * or calculating the node priority, while the actual searches for witness paths are delegated to
- * {@link WitnessPathSearcher}.
+ * {@link EdgeBasedWitnessPathSearcher}.
  *
  * @author easbar
  */
@@ -59,7 +59,7 @@ class EdgeBasedNodeContractor extends AbstractNodeContractor {
     private final StopWatch dijkstraSW = new StopWatch();
     private final SearchStrategy activeStrategy = new AggressiveStrategy();
     private int[] hierarchyDepths;
-    private WitnessPathSearcher witnessPathSearcher;
+    private EdgeBasedWitnessPathSearcher witnessPathSearcher;
     private CHEdgeExplorer existingShortcutExplorer;
     private CHEdgeExplorer allEdgeExplorer;
     private EdgeExplorer sourceNodeOrigInEdgeExplorer;
@@ -97,7 +97,7 @@ class EdgeBasedNodeContractor extends AbstractNodeContractor {
     @Override
     public void initFromGraph() {
         super.initFromGraph();
-        witnessPathSearcher = new WitnessPathSearcher(prepareGraph, turnWeighting, pMap);
+        witnessPathSearcher = new EdgeBasedWitnessPathSearcher(prepareGraph, turnWeighting, pMap);
         DefaultEdgeFilter inEdgeFilter = DefaultEdgeFilter.inEdges(encoder);
         DefaultEdgeFilter outEdgeFilter = DefaultEdgeFilter.outEdges(encoder);
         DefaultEdgeFilter allEdgeFilter = DefaultEdgeFilter.allEdges(encoder);
diff --git a/core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedWitnessPathSearcher.java
similarity index 99%
rename from core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java
rename to core/src/main/java/com/graphhopper/routing/ch/EdgeBasedWitnessPathSearcher.java
index f47a0175e..dcd87a36b 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/WitnessPathSearcher.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/EdgeBasedWitnessPathSearcher.java
@@ -61,7 +61,7 @@ import static java.lang.Double.isInfinite;
  *
  * @author easbar
  */
-public class WitnessPathSearcher {
+public class EdgeBasedWitnessPathSearcher {
     private static final int NO_NODE = -1;
     private static final double MAX_ZERO_WEIGHT_LOOP = 1.e-3;
 
@@ -107,7 +107,7 @@ public class WitnessPathSearcher {
     private final Stats currentBatchStats = new Stats();
     private final Stats totalStats = new Stats();
 
-    public WitnessPathSearcher(CHGraph chGraph, TurnWeighting turnWeighting, PMap pMap) {
+    public EdgeBasedWitnessPathSearcher(CHGraph chGraph, TurnWeighting turnWeighting, PMap pMap) {
         this.chGraph = chGraph;
         this.turnWeighting = turnWeighting;
         extractParams(pMap);
diff --git a/core/src/main/java/com/graphhopper/routing/ch/NodeBasedNodeContractor.java b/core/src/main/java/com/graphhopper/routing/ch/NodeBasedNodeContractor.java
index 0d39bdf3c..d91228c01 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/NodeBasedNodeContractor.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/NodeBasedNodeContractor.java
@@ -18,7 +18,9 @@
 package com.graphhopper.routing.ch;
 
 import com.graphhopper.routing.DijkstraOneToMany;
-import com.graphhopper.routing.util.*;
+import com.graphhopper.routing.util.DefaultEdgeFilter;
+import com.graphhopper.routing.util.IgnoreNodeFilter;
+import com.graphhopper.routing.util.TraversalMode;
 import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.CHGraph;
 import com.graphhopper.storage.Graph;
@@ -39,7 +41,7 @@ class NodeBasedNodeContractor extends AbstractNodeContractor {
     private final AddShortcutHandler addScHandler = new AddShortcutHandler();
     private final CalcShortcutHandler calcScHandler = new CalcShortcutHandler();
     private final Params params = new Params();
-    private CHEdgeExplorer remainingEdgeExplorer;
+    private CHEdgeExplorer allEdgeExplorer;
     private IgnoreNodeFilter ignoreNodeFilter;
     private DijkstraOneToMany prepareAlgo;
     private int addedShortcutsCount;
@@ -65,14 +67,7 @@ class NodeBasedNodeContractor extends AbstractNodeContractor {
     public void initFromGraph() {
         super.initFromGraph();
         ignoreNodeFilter = new IgnoreNodeFilter(prepareGraph, maxLevel);
-        final EdgeFilter allFilter = DefaultEdgeFilter.allEdges(encoder);
-        final EdgeFilter remainingNodesFilter = new LevelEdgeFilter(prepareGraph) {
-            @Override
-            public final boolean accept(EdgeIteratorState edgeState) {
-                return super.accept(edgeState) && allFilter.accept(edgeState);
-            }
-        };
-        remainingEdgeExplorer = prepareGraph.createEdgeExplorer(remainingNodesFilter);
+        allEdgeExplorer = prepareGraph.createEdgeExplorer(DefaultEdgeFilter.allEdges(encoder));
         prepareAlgo = new DijkstraOneToMany(prepareGraph, prepareWeighting, TraversalMode.NODE_BASED);
     }
 
@@ -99,6 +94,9 @@ class NodeBasedNodeContractor extends AbstractNodeContractor {
      */
     @Override
     public float calculatePriority(int node) {
+        if (prepareGraph.getLevel(node) != maxLevel) {
+            throw new IllegalArgumentException("Priority should only be calculated for not yet contracted nodes");
+        }
         CalcShortcutsResult calcShortcutsResult = calcShortcutCount(node);
 
         // # huge influence: the bigger the less shortcuts gets created and the faster is the preparation
@@ -115,11 +113,19 @@ class NodeBasedNodeContractor extends AbstractNodeContractor {
         // number of already contracted neighbors of v
         int contractedNeighbors = 0;
         int degree = 0;
-        CHEdgeIterator iter = remainingEdgeExplorer.setBaseNode(node);
+        CHEdgeIterator iter = allEdgeExplorer.setBaseNode(node);
         while (iter.next()) {
-            degree++;
-            if (iter.isShortcut())
+            // only increase the degree for edges going to equal level nodes (the current node is at maxLevel)
+            // todo: for historic reasons increase degree also for all shortcuts, even though its wrong, see #1810
+            if (iter.isShortcut() || prepareGraph.getLevel(iter.getAdjNode()) == maxLevel) {
+                degree++;
+            }
+            // todo: just because there is a shortcut it does not mean the neighbor is contracted AND
+            //       just because an edge is not a shortcut does not mean the neighbor is not contracted
+            //       see #1810
+            if (iter.isShortcut()) {
                 contractedNeighbors++;
+            }
         }
 
         // from shortcuts we can compute the edgeDifference
diff --git a/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java b/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java
index 9ec330def..a4bafe8a9 100644
--- a/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java
+++ b/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java
@@ -83,7 +83,7 @@ public class QueryGraph implements Graph {
         nodeAccess = new ExtendedNodeAccess(graph.getNodeAccess(), graphModification.getVirtualNodes(), mainNodes);
 
         if (mainGraph.getTurnCostStorage() != null)
-            turnCostStorage = new QueryGraphTurnExt(mainGraph, graphModification.getClosestEdges());
+            turnCostStorage = new QueryGraphTurnCostStorage(mainGraph, graphModification.getClosestEdges());
         else
             turnCostStorage = null;
 
diff --git a/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnExt.java b/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnCostStorage.java
similarity index 96%
rename from core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnExt.java
rename to core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnCostStorage.java
index 9f5f361ec..5cc110834 100644
--- a/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnExt.java
+++ b/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraphTurnCostStorage.java
@@ -26,13 +26,13 @@ import com.graphhopper.storage.TurnCostStorage;
 /**
  * special {@link TurnCostStorage} that handles virtual nodes and edges
  */
-class QueryGraphTurnExt extends TurnCostStorage {
+class QueryGraphTurnCostStorage extends TurnCostStorage {
     private final TurnCostStorage mainTurnCostStorage;
     private final int firstVirtualNodeId;
     private final int firstVirtualEdgeId;
     private final IntArrayList closestEdges;
 
-    QueryGraphTurnExt(Graph mainGraph, IntArrayList closestEdges) {
+    QueryGraphTurnCostStorage(Graph mainGraph, IntArrayList closestEdges) {
         super(mainGraph.getTurnCostStorage());
         this.mainTurnCostStorage = mainGraph.getTurnCostStorage();
         this.firstVirtualNodeId = mainGraph.getNodes();
diff --git a/core/src/main/java/com/graphhopper/storage/GraphHopperStorage.java b/core/src/main/java/com/graphhopper/storage/GraphHopperStorage.java
index e3f89e3f1..41e8ca77c 100644
--- a/core/src/main/java/com/graphhopper/storage/GraphHopperStorage.java
+++ b/core/src/main/java/com/graphhopper/storage/GraphHopperStorage.java
@@ -388,7 +388,7 @@ public final class GraphHopperStorage implements GraphStorage, Graph {
 
     @Override
     public int getEdges() {
-        return getAllEdges().length();
+        return baseGraph.getEdges();
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/storage/index/Location2IDFullIndex.java b/core/src/main/java/com/graphhopper/storage/index/Location2IDFullIndex.java
index b44e2baea..4aadc3b3a 100644
--- a/core/src/main/java/com/graphhopper/storage/index/Location2IDFullIndex.java
+++ b/core/src/main/java/com/graphhopper/storage/index/Location2IDFullIndex.java
@@ -19,6 +19,7 @@ package com.graphhopper.storage.index;
 
 import com.graphhopper.routing.util.AllEdgesIterator;
 import com.graphhopper.routing.util.EdgeFilter;
+import com.graphhopper.storage.CHGraph;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.util.DistanceCalc;
@@ -38,6 +39,9 @@ public class Location2IDFullIndex implements LocationIndex {
     private boolean closed = false;
 
     public Location2IDFullIndex(Graph g) {
+        if (g instanceof CHGraph)
+            throw new IllegalArgumentException("Use base graph for LocationIndex instead of CHGraph");
+
         this.graph = g;
         this.nodeAccess = g.getNodeAccess();
     }
diff --git a/core/src/main/java/com/graphhopper/storage/index/Location2IDFullWithEdgesIndex.java b/core/src/main/java/com/graphhopper/storage/index/Location2IDFullWithEdgesIndex.java
index 6d822a44c..3c55f2e67 100644
--- a/core/src/main/java/com/graphhopper/storage/index/Location2IDFullWithEdgesIndex.java
+++ b/core/src/main/java/com/graphhopper/storage/index/Location2IDFullWithEdgesIndex.java
@@ -19,6 +19,7 @@ package com.graphhopper.storage.index;
 
 import com.graphhopper.routing.util.AllEdgesIterator;
 import com.graphhopper.routing.util.EdgeFilter;
+import com.graphhopper.storage.CHGraph;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.util.DistanceCalc;
@@ -38,6 +39,9 @@ public class Location2IDFullWithEdgesIndex implements LocationIndex {
     private boolean closed = false;
 
     public Location2IDFullWithEdgesIndex(Graph g) {
+        if (g instanceof CHGraph)
+            throw new IllegalArgumentException("Use base graph for LocationIndex instead of CHGraph");
+
         this.graph = g;
         this.nodeAccess = g.getNodeAccess();
     }
diff --git a/core/src/main/java/com/graphhopper/storage/index/Location2IDQuadtree.java b/core/src/main/java/com/graphhopper/storage/index/Location2IDQuadtree.java
index 59445254a..f80a29c34 100644
--- a/core/src/main/java/com/graphhopper/storage/index/Location2IDQuadtree.java
+++ b/core/src/main/java/com/graphhopper/storage/index/Location2IDQuadtree.java
@@ -58,6 +58,9 @@ class Location2IDQuadtree implements LocationIndex {
     private int lonSize, latSize;
 
     public Location2IDQuadtree(Graph g, Directory dir) {
+        if (g instanceof CHGraph)
+            throw new IllegalArgumentException("Use base graph for LocationIndex instead of CHGraph");
+
         this.graph = g;
         this.nodeAccess = g.getNodeAccess();
         index = dir.find("loc2id_index");
diff --git a/core/src/main/java/com/graphhopper/util/GHUtility.java b/core/src/main/java/com/graphhopper/util/GHUtility.java
index 5a969cf92..5c3c64a3f 100644
--- a/core/src/main/java/com/graphhopper/util/GHUtility.java
+++ b/core/src/main/java/com/graphhopper/util/GHUtility.java
@@ -122,7 +122,7 @@ public class GHUtility {
     }
 
     public static void printEdgeInfo(final Graph g, FlagEncoder encoder) {
-        System.out.println("-- Graph nodes:" + g.getNodes() + " edges:" + g.getAllEdges().length() + " ---");
+        System.out.println("-- Graph nodes:" + g.getNodes() + " edges:" + g.getEdges() + " ---");
         AllEdgesIterator iter = g.getAllEdges();
         BooleanEncodedValue accessEnc = encoder.getAccessEnc();
         while (iter.next()) {
@@ -216,7 +216,7 @@ public class GHUtility {
         }
         LOGGER.debug(String.format(Locale.ROOT, "Finished building random graph" +
                         ", nodes: %d, edges: %d , min distance: %.2f, max distance: %.2f\n",
-                graph.getNodes(), graph.getAllEdges().length(), minDist, maxDist));
+                graph.getNodes(), graph.getEdges(), minDist, maxDist));
     }
 
     public static double getDistance(int from, int to, NodeAccess nodeAccess) {
diff --git a/core/src/main/resources/com/graphhopper/util/ar.txt b/core/src/main/resources/com/graphhopper/util/ar.txt
index 2001ff7a2..524a7a26d 100644
--- a/core/src/main/resources/com/graphhopper/util/ar.txt
+++ b/core/src/main/resources/com/graphhopper/util/ar.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=في الدوران ، أتخذ مخرج   %1$s من خلا
 total_ascend=%1$s اجمالى صعود
 total_descend=%1$s اجمالى نزول
 way_contains_ford=هناك مخاضة على طول الطريق
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=ادخل %1$s
 pt_end_trip=مغادرة %1$s
 pt_transfer_to=انتقل الى %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/ast.txt b/core/src/main/resources/com/graphhopper/util/ast.txt
index 22526b0c8..865773609 100644
--- a/core/src/main/resources/com/graphhopper/util/ast.txt
+++ b/core/src/main/resources/com/graphhopper/util/ast.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Na rotonda, toma la salida %1$s haza %2$s
 total_ascend=%1$s d'ascensu total
 total_descend=%1$s de descensu total
 way_contains_ford=hai un vau nel camín
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=xubi a  %1$s
 pt_end_trip=baxa de  %1$s
 pt_transfer_to=cambia a  %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/bg.txt b/core/src/main/resources/com/graphhopper/util/bg.txt
index 6055342b1..5cf0079ac 100644
--- a/core/src/main/resources/com/graphhopper/util/bg.txt
+++ b/core/src/main/resources/com/graphhopper/util/bg.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=На кръговото кръстовище използв
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/ca.txt b/core/src/main/resources/com/graphhopper/util/ca.txt
index 14d2f3ac4..630c490af 100644
--- a/core/src/main/resources/com/graphhopper/util/ca.txt
+++ b/core/src/main/resources/com/graphhopper/util/ca.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=A la rotonda, agafa la %1$sa sortida cap a %2$s
 total_ascend=%1$s de pujada total
 total_descend=%1$s de baixada total
 way_contains_ford=hi ha un gual en el camí
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=entra a %1$s
 pt_end_trip=surt de %1$s
 pt_transfer_to=canvia a %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/cs_CZ.txt b/core/src/main/resources/com/graphhopper/util/cs_CZ.txt
index 315d712d5..46be7976c 100644
--- a/core/src/main/resources/com/graphhopper/util/cs_CZ.txt
+++ b/core/src/main/resources/com/graphhopper/util/cs_CZ.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Na kruhovém objezdu použijte %1$s. výjezd, směrem na %2
 total_ascend=Celkové stoupání %1$s
 total_descend=Celkové klesání %1$s
 way_contains_ford=na cestě je brod
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=nastupte do %1$s
 pt_end_trip=vystupte z %1$s
 pt_transfer_to=přestupte na %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/da_DK.txt b/core/src/main/resources/com/graphhopper/util/da_DK.txt
index 1368e20d5..a404bda73 100644
--- a/core/src/main/resources/com/graphhopper/util/da_DK.txt
+++ b/core/src/main/resources/com/graphhopper/util/da_DK.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=I rundskørslen, tag udkørsel %1$s ind på %2$s
 total_ascend=%1$s samlet stigning
 total_descend=%1$s samlet fald
 way_contains_ford=der er et vadested undervejs
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=stig på %1$s
 pt_end_trip=stig af %1$s
 pt_transfer_to=omstigning til %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/de_DE.txt b/core/src/main/resources/com/graphhopper/util/de_DE.txt
index d2effe7e9..162348564 100644
--- a/core/src/main/resources/com/graphhopper/util/de_DE.txt
+++ b/core/src/main/resources/com/graphhopper/util/de_DE.txt
@@ -56,7 +56,10 @@ roundabout_exit=Im Kreisverkehr Ausfahrt %1$s nehmen
 roundabout_exit_onto=Im Kreisverkehr Ausfahrt %1$s auf %2$s nehmen
 total_ascend=%1$s Gesamtaufstieg
 total_descend=%1$s Gesamtabstieg
-way_contains_ford=es liegt eine Furt auf dem Weg
+way_contains_ford=Achtung, es liegt eine Furt auf dem Weg
+way_contains_ferry=die Fähre nehmen
+way_contains_private=Privatweg
+way_contains_toll=Mautpflichtige Straße
 pt_start_trip=einsteigen in %1$s
 pt_end_trip=aus %1$s aussteigen
 pt_transfer_to=umsteigen auf %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/el.txt b/core/src/main/resources/com/graphhopper/util/el.txt
index f41bb708e..936f48251 100644
--- a/core/src/main/resources/com/graphhopper/util/el.txt
+++ b/core/src/main/resources/com/graphhopper/util/el.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Στον κυκλικό κόμβο βγείτε στην έ
 total_ascend=%1$s συνολική ανάβαση
 total_descend=%1$s συνολική κατάβαση
 way_contains_ford=υπάρχει πέρασμα στο δρόμο
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=μπείτε στο %1$s
 pt_end_trip=αφήστε το %1$s
 pt_transfer_to=αλλάξτε στο %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/en_US.txt b/core/src/main/resources/com/graphhopper/util/en_US.txt
index 6c5a4afcb..77eea88bf 100644
--- a/core/src/main/resources/com/graphhopper/util/en_US.txt
+++ b/core/src/main/resources/com/graphhopper/util/en_US.txt
@@ -56,7 +56,10 @@ roundabout_exit=At roundabout, take exit %1$s
 roundabout_exit_onto=At roundabout, take exit %1$s onto %2$s
 total_ascend=%1$s total ascent
 total_descend=%1$s total descent
-way_contains_ford=there is a ford along the way
+way_contains_ford=Attention, there is a ford on the way
+way_contains_ferry=take the ferry
+way_contains_private=private road
+way_contains_toll=toll road
 pt_start_trip=enter %1$s
 pt_end_trip=leave %1$s
 pt_transfer_to=change to %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/eo.txt b/core/src/main/resources/com/graphhopper/util/eo.txt
index f58d54232..1b268092d 100644
--- a/core/src/main/resources/com/graphhopper/util/eo.txt
+++ b/core/src/main/resources/com/graphhopper/util/eo.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Ĉe trafikcirklo, elveturu al %1$s-a vojo al %2$s
 total_ascend=%1$s supreniro tute
 total_descend=%1$s malsupreniro tute
 way_contains_ford=travadejo sur la kurso
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=eniru al %1$s
 pt_end_trip=eliru el %1$s
 pt_transfer_to=transveturiĝu al %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/es.txt b/core/src/main/resources/com/graphhopper/util/es.txt
index 20fa1d79b..54b490ff3 100644
--- a/core/src/main/resources/com/graphhopper/util/es.txt
+++ b/core/src/main/resources/com/graphhopper/util/es.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=En la rotonda, toma la %1$sª salida hacia %2$s
 total_ascend=Ascender %1$s en total
 total_descend=Descender %1$s en total
 way_contains_ford=hay un vado en el camino
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=entra en %1$s
 pt_end_trip=sal de %1$s
 pt_transfer_to=cambia a %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/fa.txt b/core/src/main/resources/com/graphhopper/util/fa.txt
index 0dcbb3fb6..6a8c642ab 100644
--- a/core/src/main/resources/com/graphhopper/util/fa.txt
+++ b/core/src/main/resources/com/graphhopper/util/fa.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=در فلکه، از خروجی %1$s به %2$s بروید
 total_ascend=مجموع صعود %1$s
 total_descend=مجموع نزول %1$s
 way_contains_ford=در طول مسیر گُدار وجود دارد
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=وارد %1$s شوید
 pt_end_trip=از %1$s خارج شوید
 pt_transfer_to=مسیر را به %1$s تغییر دهید
diff --git a/core/src/main/resources/com/graphhopper/util/fi.txt b/core/src/main/resources/com/graphhopper/util/fi.txt
index 61ad64f0f..fe417eb0e 100644
--- a/core/src/main/resources/com/graphhopper/util/fi.txt
+++ b/core/src/main/resources/com/graphhopper/util/fi.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Liikenneympyrästä poistu %1$s. liittymästä suuntaan %2$
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/fil.txt b/core/src/main/resources/com/graphhopper/util/fil.txt
index c0e35c960..94e2f3d98 100644
--- a/core/src/main/resources/com/graphhopper/util/fil.txt
+++ b/core/src/main/resources/com/graphhopper/util/fil.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Sa rotonda, lumabas sa exit papunta %1$s %2$s
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/fr_CH.txt b/core/src/main/resources/com/graphhopper/util/fr_CH.txt
index 8e0250b17..aaf5f40bc 100644
--- a/core/src/main/resources/com/graphhopper/util/fr_CH.txt
+++ b/core/src/main/resources/com/graphhopper/util/fr_CH.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Au giratoire, prenez la %1$s sortie vers %2$s
 total_ascend=%1$s de dénivelé positif
 total_descend=%1$s de dénivelé négatif
 way_contains_ford=cet itinéraire comprend un passage à gué
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=montez dans %1$s
 pt_end_trip=descendez de %1$s
 pt_transfer_to=changez vers %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/fr_FR.txt b/core/src/main/resources/com/graphhopper/util/fr_FR.txt
index b44ef193e..5ebbc2f02 100644
--- a/core/src/main/resources/com/graphhopper/util/fr_FR.txt
+++ b/core/src/main/resources/com/graphhopper/util/fr_FR.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Au rond-point, prenez la %1$s sortie vers %2$s
 total_ascend=%1$s de dénivelé positif
 total_descend=%1$s de dénivelé négatif
 way_contains_ford=cet itinéraire comprend un passage à gué
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=montez dans %1$s
 pt_end_trip=descendez de %1$s
 pt_transfer_to=changez vers %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/gl.txt b/core/src/main/resources/com/graphhopper/util/gl.txt
index a2af35de5..7e6e4310e 100644
--- a/core/src/main/resources/com/graphhopper/util/gl.txt
+++ b/core/src/main/resources/com/graphhopper/util/gl.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Na rotonda, tome a saída %1$s cara %2$s
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/he.txt b/core/src/main/resources/com/graphhopper/util/he.txt
index 6f18866ac..010a2bb56 100644
--- a/core/src/main/resources/com/graphhopper/util/he.txt
+++ b/core/src/main/resources/com/graphhopper/util/he.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=בכיכר, יש לצאת ביציאה %1$s לתוך %2$s
 total_ascend=עלייה כוללת של %1$s
 total_descend=ירידה כוללת של %1$s
 way_contains_ford=יש מעבר מים לאורך הדרך
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=יש להיכנס אל %1$s
 pt_end_trip=יש לצאת מ%1$s
 pt_transfer_to=להחליף ל%1$s
diff --git a/core/src/main/resources/com/graphhopper/util/hr_HR.txt b/core/src/main/resources/com/graphhopper/util/hr_HR.txt
index 2305016a7..c4b0d5d0a 100644
--- a/core/src/main/resources/com/graphhopper/util/hr_HR.txt
+++ b/core/src/main/resources/com/graphhopper/util/hr_HR.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Sa kružnog toka izađite na izlaz %1$s na %2$s
 total_ascend=%1$s ukupni uspon
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/hsb.txt b/core/src/main/resources/com/graphhopper/util/hsb.txt
index 66d02daa3..eefc4cd58 100644
--- a/core/src/main/resources/com/graphhopper/util/hsb.txt
+++ b/core/src/main/resources/com/graphhopper/util/hsb.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=we kružnym wobchadźe %1$s. wujězd na %2$s wzać
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/hu_HU.txt b/core/src/main/resources/com/graphhopper/util/hu_HU.txt
index 3dbd45764..cf472ef2f 100644
--- a/core/src/main/resources/com/graphhopper/util/hu_HU.txt
+++ b/core/src/main/resources/com/graphhopper/util/hu_HU.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Hajtson ki a körforgalomból itt: %1$s. kijárat, majd haj
 total_ascend=Összes szintemelkedés: %1$s
 total_descend=Összes szintcsökkenés: %1$s
 way_contains_ford=gázló van az útvonalon
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=szálljon fel erre: %1$s
 pt_end_trip=szálljon le erről: %1$s
 pt_transfer_to=szálljon át erre: %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/in_ID.txt b/core/src/main/resources/com/graphhopper/util/in_ID.txt
index fe7f6e5bb..8741d5c6c 100644
--- a/core/src/main/resources/com/graphhopper/util/in_ID.txt
+++ b/core/src/main/resources/com/graphhopper/util/in_ID.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=At roundabout, take exit %1$s onto %2$s
 total_ascend=naik dengan jarak %1$s
 total_descend=turun dengan jarak %1$s
 way_contains_ford=terdapat jalan untuk dilewati
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=masuk dalam %1$s
 pt_end_trip=keluar dalam %1$s
 pt_transfer_to=berpindah ke jalur %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/it.txt b/core/src/main/resources/com/graphhopper/util/it.txt
index 2173685fe..10ee7c430 100644
--- a/core/src/main/resources/com/graphhopper/util/it.txt
+++ b/core/src/main/resources/com/graphhopper/util/it.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Nella rotatoria, prendere l'uscita %1$s su %2$s
 total_ascend=%1$s di dislivello positivo
 total_descend=%1$s di dislivello negativo
 way_contains_ford=c'é un guado sulla strada
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=prendi %1$s
 pt_end_trip=lascia %1$s
 pt_transfer_to=cambia con %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/ja.txt b/core/src/main/resources/com/graphhopper/util/ja.txt
index 35c21e5a9..172ff0a21 100644
--- a/core/src/main/resources/com/graphhopper/util/ja.txt
+++ b/core/src/main/resources/com/graphhopper/util/ja.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=円形交差点の出口%1$sから%2$sへ
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/ko.txt b/core/src/main/resources/com/graphhopper/util/ko.txt
index 0fc92d946..d9c77c41d 100644
--- a/core/src/main/resources/com/graphhopper/util/ko.txt
+++ b/core/src/main/resources/com/graphhopper/util/ko.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=회전교차로에서 %1$s 진출 후 %2$s 이동
 total_ascend=오르막길 총 %1$s
 total_descend=내리막길 총 %1$s
 way_contains_ford=경로에 여울이 있습니다
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=%1$s 진입
 pt_end_trip=%1$s 진출
 pt_transfer_to=%1$s(으)로 환승
diff --git a/core/src/main/resources/com/graphhopper/util/lt_LT.txt b/core/src/main/resources/com/graphhopper/util/lt_LT.txt
index c067cbb95..4aa3b0d8d 100644
--- a/core/src/main/resources/com/graphhopper/util/lt_LT.txt
+++ b/core/src/main/resources/com/graphhopper/util/lt_LT.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Žiede išvažiuokite %1$s išvažiavime į  %2$s
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/ne.txt b/core/src/main/resources/com/graphhopper/util/ne.txt
index 9810a0601..805f6c016 100644
--- a/core/src/main/resources/com/graphhopper/util/ne.txt
+++ b/core/src/main/resources/com/graphhopper/util/ne.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=घुम्तीमा %1$s नम्बर को मो
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/nl.txt b/core/src/main/resources/com/graphhopper/util/nl.txt
index 838aa76b9..9797959b5 100644
--- a/core/src/main/resources/com/graphhopper/util/nl.txt
+++ b/core/src/main/resources/com/graphhopper/util/nl.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=neem afslag %1$s naar %2$s op de rotonde
 total_ascend=%1$s totale klim
 total_descend=%1$s totale daling
 way_contains_ford=Er is een doorwaadbare plaats
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=Neem de %1$s
 pt_end_trip=Stap uit de %1$s uit
 pt_transfer_to=Stap over op de %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/pl_PL.txt b/core/src/main/resources/com/graphhopper/util/pl_PL.txt
index 9861ac9b2..56bf312fb 100644
--- a/core/src/main/resources/com/graphhopper/util/pl_PL.txt
+++ b/core/src/main/resources/com/graphhopper/util/pl_PL.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Zjedź z ronda %1$s zjazdem na %2$s
 total_ascend=%1$s podejść ogółem
 total_descend=%1$s zejść ogółem
 way_contains_ford=bród na trasie
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=wsiądź w %1$s
 pt_end_trip=wysiądź z %1$s
 pt_transfer_to=przesiądź się na %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/pt_BR.txt b/core/src/main/resources/com/graphhopper/util/pt_BR.txt
index b8ff9ff6b..184cbcb98 100644
--- a/core/src/main/resources/com/graphhopper/util/pt_BR.txt
+++ b/core/src/main/resources/com/graphhopper/util/pt_BR.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Na rotatória, saia na %1$s saida em direção a %2$s
 total_ascend=subida de %1$s
 total_descend=descida de %1$s
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=embarque %1$s
 pt_end_trip=desembarque %1$s
 pt_transfer_to=mude para %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/pt_PT.txt b/core/src/main/resources/com/graphhopper/util/pt_PT.txt
index b1bf52a56..0964ea613 100644
--- a/core/src/main/resources/com/graphhopper/util/pt_PT.txt
+++ b/core/src/main/resources/com/graphhopper/util/pt_PT.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Na rotunda, saia na %1$s saida em direção a %2$s
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/ro.txt b/core/src/main/resources/com/graphhopper/util/ro.txt
index 93b8c7bbd..161a7cfa5 100644
--- a/core/src/main/resources/com/graphhopper/util/ro.txt
+++ b/core/src/main/resources/com/graphhopper/util/ro.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=În sensul giratoriu folosiți ieșirea %1$s către %2$s
 total_ascend=urcare %1$s
 total_descend=coborâre %1$s
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/ru.txt b/core/src/main/resources/com/graphhopper/util/ru.txt
index 3a7cbe689..c27daa646 100644
--- a/core/src/main/resources/com/graphhopper/util/ru.txt
+++ b/core/src/main/resources/com/graphhopper/util/ru.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Сверните на %1$s-й съезд на %2$s
 total_ascend=подъём на %1$s
 total_descend=спуск на %1$s
 way_contains_ford=На пути есть брод
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=Сядьте на %1$s
 pt_end_trip=Выйдите из %1$s
 pt_transfer_to=Пересядьте на %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/sk.txt b/core/src/main/resources/com/graphhopper/util/sk.txt
index c1450f93b..fe552204d 100644
--- a/core/src/main/resources/com/graphhopper/util/sk.txt
+++ b/core/src/main/resources/com/graphhopper/util/sk.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Na kruhovom objazde, ho opustite cez %1$s. výjazd na %2$s
 total_ascend=%1$s celkové stúpanie
 total_descend=%1$s celkové klesanie
 way_contains_ford=popri ceste sa nachádza brod
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=nastúpte na linku %1$s
 pt_end_trip=vystúpte z linky %1$s
 pt_transfer_to=prestúpte na linku %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/sl_SI.txt b/core/src/main/resources/com/graphhopper/util/sl_SI.txt
index 1b1bf95c6..72c9ea901 100644
--- a/core/src/main/resources/com/graphhopper/util/sl_SI.txt
+++ b/core/src/main/resources/com/graphhopper/util/sl_SI.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=V krožišču uporabite %1$s. izhod, da zavijete na %2$s
 total_ascend=Skupni vzpon: %1$s
 total_descend=Skupni spust: %1$s
 way_contains_ford=Na poti je pregaz
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=Vstopite v/na %1$s
 pt_end_trip=Zapustite %1$s
 pt_transfer_to=Prestopite na %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/sr_RS.txt b/core/src/main/resources/com/graphhopper/util/sr_RS.txt
index 506d12ba2..35a212b15 100644
--- a/core/src/main/resources/com/graphhopper/util/sr_RS.txt
+++ b/core/src/main/resources/com/graphhopper/util/sr_RS.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Sa kružnog toka izađite na izlaz %1$s na %2$s
 total_ascend=%1$s ukupni uspon
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/sv_SE.txt b/core/src/main/resources/com/graphhopper/util/sv_SE.txt
index 49da3864d..cae593744 100644
--- a/core/src/main/resources/com/graphhopper/util/sv_SE.txt
+++ b/core/src/main/resources/com/graphhopper/util/sv_SE.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=I rondellen, ta avfart %1$s in på %2$s
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/tr.txt b/core/src/main/resources/com/graphhopper/util/tr.txt
index 8788bd90d..8db019116 100644
--- a/core/src/main/resources/com/graphhopper/util/tr.txt
+++ b/core/src/main/resources/com/graphhopper/util/tr.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=kavşaktan %1$s cıkıştan %2$s sokağa gir
 total_ascend=
 total_descend=
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/uk.txt b/core/src/main/resources/com/graphhopper/util/uk.txt
index 34e536fd7..999f9535e 100644
--- a/core/src/main/resources/com/graphhopper/util/uk.txt
+++ b/core/src/main/resources/com/graphhopper/util/uk.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=На кільці використовуйте з’їзд
 total_ascend=%1$s загалом підйому
 total_descend=%1$s загалом спуску
 way_contains_ford=На шляху є брід
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=Сядьте на %1$s
 pt_end_trip=Вийдіть з %1$s
 pt_transfer_to=Пересядьте на %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/vi_VN.txt b/core/src/main/resources/com/graphhopper/util/vi_VN.txt
index 659d4e113..f50890c8c 100644
--- a/core/src/main/resources/com/graphhopper/util/vi_VN.txt
+++ b/core/src/main/resources/com/graphhopper/util/vi_VN.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=Tại vòng xoay, rẽ lối rẽ %1$s vào đường %2$s
 total_ascend=Đi tiếp %1$s nữa
 total_descend=
 way_contains_ford=có khúc sông cạn trên đường
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=nhập tuyến %1$s
 pt_end_trip=rời tuyến %1$s
 pt_transfer_to=chuyển sang tuyến %1$s
diff --git a/core/src/main/resources/com/graphhopper/util/zh_CN.txt b/core/src/main/resources/com/graphhopper/util/zh_CN.txt
index c4eec2a12..990fbd880 100644
--- a/core/src/main/resources/com/graphhopper/util/zh_CN.txt
+++ b/core/src/main/resources/com/graphhopper/util/zh_CN.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=在环岛内，使用%1$s出口出环岛，进入%2$s
 total_ascend=总上升%1$s
 total_descend=总下降%1$s
 way_contains_ford=路径中包含河滩
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=进入%1$s
 pt_end_trip=离开%1$s
 pt_transfer_to=变道进入%1$s
diff --git a/core/src/main/resources/com/graphhopper/util/zh_HK.txt b/core/src/main/resources/com/graphhopper/util/zh_HK.txt
index b9f7c630b..c7253582c 100644
--- a/core/src/main/resources/com/graphhopper/util/zh_HK.txt
+++ b/core/src/main/resources/com/graphhopper/util/zh_HK.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=使用 %1$s 出口離開迴旋處到 %2$s
 total_ascend=總共上昇 %1$s
 total_descend=總共下降 %1$s
 way_contains_ford=
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=
 pt_end_trip=
 pt_transfer_to=
diff --git a/core/src/main/resources/com/graphhopper/util/zh_TW.txt b/core/src/main/resources/com/graphhopper/util/zh_TW.txt
index a91fd1775..fdf6128a4 100644
--- a/core/src/main/resources/com/graphhopper/util/zh_TW.txt
+++ b/core/src/main/resources/com/graphhopper/util/zh_TW.txt
@@ -57,6 +57,9 @@ roundabout_exit_onto=於 %1$s 個出口離開圓環，進入 %2$s
 total_ascend=總共上昇 %1$s
 total_descend=總共下降 %1$s
 way_contains_ford=路徑中含有淺灘
+way_contains_ferry=
+way_contains_private=
+way_contains_toll=
 pt_start_trip=進入 %1$s
 pt_end_trip=離開 %1$s
 pt_transfer_to=變換至 %1$s
diff --git a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/RealtimeFeed.java b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/RealtimeFeed.java
index 8c12bf4b8..4fae07f3b 100644
--- a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/RealtimeFeed.java
+++ b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/RealtimeFeed.java
@@ -102,7 +102,7 @@ public class RealtimeFeed {
         final IntLongHashMap delaysForAlightEdges = new IntLongHashMap();
         final LinkedList<VirtualEdgeIteratorState> additionalEdges = new LinkedList<>();
         final Graph overlayGraph = new Graph() {
-            int firstEdge = graphHopperStorage.getAllEdges().length();
+            int firstEdge = graphHopperStorage.getEdges();
             EncodingManager encodingManager = graphHopperStorage.getEncodingManager();
             final NodeAccess nodeAccess = new NodeAccess() {
                 IntIntHashMap turnCostIndices = new IntIntHashMap();


Test patch:
diff --git a/core/src/test/java/com/graphhopper/routing/ch/WitnessPathSearcherTest.java b/core/src/test/java/com/graphhopper/routing/ch/EdgeBasedWitnessPathSearcherTest.java
similarity index 92%
rename from core/src/test/java/com/graphhopper/routing/ch/WitnessPathSearcherTest.java
rename to core/src/test/java/com/graphhopper/routing/ch/EdgeBasedWitnessPathSearcherTest.java
index aa6f24f53..946f24713 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/WitnessPathSearcherTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/EdgeBasedWitnessPathSearcherTest.java
@@ -33,7 +33,7 @@ import static com.graphhopper.routing.weighting.TurnWeighting.INFINITE_U_TURN_CO
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-public class WitnessPathSearcherTest {
+public class EdgeBasedWitnessPathSearcherTest {
 
     private GraphHopperStorage graph;
     private CHGraph chGraph;
@@ -60,7 +60,7 @@ public class WitnessPathSearcherTest {
         graph.edge(3, 4, 1, false);
         graph.freeze();
         setMaxLevelOnAllNodes();
-        WitnessPathSearcher finder = createFinder();
+        EdgeBasedWitnessPathSearcher finder = createFinder();
         finder.initSearch(2, 1, 0);
         CHEntry result = finder.runSearch(3, 3);
         CHEntry expected = new ExpectedResultBuilder(3, 2, 2, 2.0)
@@ -78,7 +78,7 @@ public class WitnessPathSearcherTest {
         graph.edge(3, 4, 1, true);
         graph.freeze();
         setMaxLevelOnAllNodes();
-        WitnessPathSearcher finder = createFinder();
+        EdgeBasedWitnessPathSearcher finder = createFinder();
         finder.initSearch(2, 1, 0);
         CHEntry result = finder.runSearch(3, 3);
         CHEntry expected = new ExpectedResultBuilder(3, 2, 2, 2.0)
@@ -100,7 +100,7 @@ public class WitnessPathSearcherTest {
         graph.edge(5, 3, 1, false);
         graph.freeze();
         setMaxLevelOnAllNodes();
-        WitnessPathSearcher finder = createFinder();
+        EdgeBasedWitnessPathSearcher finder = createFinder();
         finder.initSearch(2, 1, 0);
         CHEntry result = finder.runSearch(3, 3);
         assertNull(result);
@@ -119,14 +119,14 @@ public class WitnessPathSearcherTest {
         graph.edge(5, 3, 1, true);
         graph.freeze();
         setMaxLevelOnAllNodes();
-        WitnessPathSearcher finder = createFinder();
+        EdgeBasedWitnessPathSearcher finder = createFinder();
         finder.initSearch(2, 1, 0);
         CHEntry result = finder.runSearch(3, 3);
         assertNull(result);
     }
 
-    private WitnessPathSearcher createFinder() {
-        return new WitnessPathSearcher(chGraph, chTurnWeighting, new PMap());
+    private EdgeBasedWitnessPathSearcher createFinder() {
+        return new EdgeBasedWitnessPathSearcher(chGraph, chTurnWeighting, new PMap());
     }
 
     private void setMaxLevelOnAllNodes() {
diff --git a/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java b/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java
index 60d95a92a..94581afa2 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java
@@ -49,13 +49,14 @@ public class PrepareContractionHierarchiesTest {
     private final Weighting weighting = new ShortestWeighting(carEncoder);
     private final CHProfile chProfile = CHProfile.nodeBased(weighting);
     private final TraversalMode tMode = TraversalMode.NODE_BASED;
-    private Directory dir;
+    private GraphHopperStorage g;
+    private CHGraph lg;
 
     // 0-1-.....-9-10
     // |         ^   \
     // |         |    |
     // 17-16-...-11<-/
-    public static void initDirected2(Graph g) {
+    private static void initDirected2(Graph g) {
         g.edge(0, 1, 1, true);
         g.edge(1, 2, 1, true);
         g.edge(2, 3, 1, true);
@@ -77,29 +78,8 @@ public class PrepareContractionHierarchiesTest {
         g.edge(17, 0, 1, true);
     }
 
-    //       8
-    //       |
-    //    6->0->1->3->7
-    //    |        |
-    //    |        v
-    //10<-2---4<---5
-    //    9
-    public static void initDirected1(Graph g) {
-        g.edge(0, 8, 1, true);
-        g.edge(0, 1, 1, false);
-        g.edge(1, 3, 1, false);
-        g.edge(3, 7, 1, false);
-        g.edge(3, 5, 1, false);
-        g.edge(5, 4, 1, false);
-        g.edge(4, 2, 1, true);
-        g.edge(2, 9, 1, false);
-        g.edge(2, 10, 1, false);
-        g.edge(2, 6, 1, true);
-        g.edge(6, 0, 1, false);
-    }
-
     // prepare-routing.svg
-    public static Graph initShortcutsGraph(Graph g) {
+    private static void initShortcutsGraph(Graph g) {
         g.edge(0, 1, 1, true);
         g.edge(0, 2, 1, true);
         g.edge(1, 2, 1, true);
@@ -122,20 +102,9 @@ public class PrepareContractionHierarchiesTest {
         g.edge(13, 16, 1, true);
         g.edge(15, 16, 2, true);
         g.edge(14, 16, 1, true);
-        return g;
-    }
-
-    GraphHopperStorage createGHStorage() {
-        return createGHStorage(chProfile);
-    }
-
-    GraphHopperStorage createGHStorage(CHProfile p) {
-        return new GraphBuilder(encodingManager).setCHProfiles(p).create();
     }
 
-    GraphHopperStorage createExampleGraph() {
-        GraphHopperStorage g = createGHStorage();
-
+    private static void initExampleGraph(Graph g) {
         //5-1-----2
         //   \ __/|
         //    0   |
@@ -149,17 +118,24 @@ public class PrepareContractionHierarchiesTest {
         g.edge(2, 3, 1, true);
         g.edge(4, 3, 2, true);
         g.edge(5, 1, 2, true);
-        return g;
     }
 
     @Before
     public void setUp() {
-        dir = new GHDirectory("", DAType.RAM_INT);
+        g = createGHStorage();
+        lg = g.getCHGraph();
+    }
+
+    private GraphHopperStorage createGHStorage() {
+        return createGHStorage(chProfile);
+    }
+
+    private GraphHopperStorage createGHStorage(CHProfile p) {
+        return new GraphBuilder(encodingManager).setCHProfiles(p).create();
     }
 
     @Test
     public void testReturnsCorrectWeighting() {
-        GraphHopperStorage g = createGHStorage();
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         prepare.doWork();
         assertSame(weighting, prepare.getWeighting());
@@ -167,8 +143,7 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testAddShortcuts() {
-        GraphHopperStorage g = createExampleGraph();
-        CHGraph lg = g.getCHGraph();
+        initExampleGraph(g);
         int old = lg.getEdges();
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         prepare.doWork();
@@ -177,19 +152,16 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testMoreComplexGraph() {
-        GraphHopperStorage g = createGHStorage();
         initShortcutsGraph(g);
-        int oldCount = g.getAllEdges().length();
+        int oldCount = g.getEdges();
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         prepare.doWork();
-        CHGraph lg = g.getCHGraph();
         assertEquals(oldCount, g.getEdges());
         assertEquals(oldCount + 7, lg.getEdges());
     }
 
     @Test
     public void testDirectedGraph() {
-        GraphHopperStorage g = createGHStorage();
         g.edge(5, 4, 3, false);
         g.edge(4, 5, 10, false);
         g.edge(2, 4, 1, false);
@@ -197,13 +169,13 @@ public class PrepareContractionHierarchiesTest {
         g.edge(3, 5, 1, false);
         g.edge(4, 3, 1, false);
         g.freeze();
-        CHGraph lg = g.getCHGraph();
-        int oldCount = GHUtility.count(lg.getAllEdges());
+        int oldCount = lg.getEdges();
         assertEquals(6, oldCount);
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         prepare.doWork();
         assertEquals(2, prepare.getShortcuts());
-        assertEquals(oldCount + 2, GHUtility.count(lg.getAllEdges()));
+        assertEquals(oldCount, lg.getOriginalEdges());
+        assertEquals(oldCount + 2,lg.getEdges());
         RoutingAlgorithm algo = prepare.createAlgo(lg, new AlgorithmOptions(DIJKSTRA_BI, weighting, tMode));
         Path p = algo.calcPath(4, 2);
         assertEquals(3, p.getDistance(), 1e-6);
@@ -212,19 +184,18 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testDirectedGraph2() {
-        GraphHopperStorage g = createGHStorage();
         initDirected2(g);
-        int oldCount = GHUtility.count(g.getAllEdges());
+        int oldCount = g.getEdges();
         assertEquals(19, oldCount);
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         prepare.doWork();
-        CHGraph lg = g.getCHGraph();
         // PrepareTowerNodesShortcutsTest.printEdges(g);
-        assertEquals(oldCount, g.getAllEdges().length());
+        assertEquals(oldCount, g.getEdges());
         assertEquals(oldCount, GHUtility.count(g.getAllEdges()));
 
         long numShortcuts = 9;
         assertEquals(numShortcuts, prepare.getShortcuts());
+        assertEquals(oldCount, lg.getOriginalEdges());
         assertEquals(oldCount + numShortcuts, lg.getEdges());
         assertEquals(oldCount + numShortcuts, GHUtility.count(lg.getAllEdges()));
         RoutingAlgorithm algo = prepare.createAlgo(lg, new AlgorithmOptions(DIJKSTRA_BI, weighting, tMode));
@@ -233,7 +204,7 @@ public class PrepareContractionHierarchiesTest {
         assertEquals(IntArrayList.from(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10), p.calcNodes());
     }
 
-    void initRoundaboutGraph(Graph g) {
+    private void initRoundaboutGraph(Graph g) {
         //              roundabout:
         //16-0-9-10--11   12<-13
         //    \       \  /      \
@@ -286,13 +257,12 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testRoundaboutUnpacking() {
-        GraphHopperStorage g = createGHStorage();
         initRoundaboutGraph(g);
-        int oldCount = g.getAllEdges().length();
+        int oldCount = g.getEdges();
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         prepare.doWork();
-        CHGraph lg = g.getCHGraph();
         assertEquals(oldCount, g.getEdges());
+        assertEquals(oldCount, lg.getOriginalEdges());
         assertEquals(oldCount + 23, lg.getEdges());
         RoutingAlgorithm algo = prepare.createAlgo(lg, new AlgorithmOptions(DIJKSTRA_BI, weighting, tMode));
         Path p = algo.calcPath(4, 7);
@@ -349,8 +319,6 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testUnpackingOrder() {
-        GraphHopperStorage g = createGHStorage();
-        CHGraph lg = g.getCHGraph();
         initUnpackingGraph(g, lg, weighting);
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g);
         // do not call prepare.doWork() here
@@ -362,8 +330,6 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testUnpackingOrder_Fastest() {
-        GraphHopperStorage g = createGHStorage();
-        CHGraph lg = g.getCHGraph();
         Weighting w = new FastestWeighting(carEncoder);
         initUnpackingGraph(g, lg, w);
 
@@ -377,7 +343,6 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testDisconnects() {
-        final GraphHopperStorage g = createGHStorage();
         //            4
         //            v
         //            0
@@ -410,7 +375,6 @@ public class PrepareContractionHierarchiesTest {
                     }
                 });
         prepare.doWork();
-        CHGraph lg = g.getCHGraph();
         CHEdgeExplorer explorer = lg.createEdgeExplorer();
         // shortcuts (and edges) leading to or coming from lower level nodes should be disconnected
         // so far we are only disconnecting shortcuts however, see comments in CHGraphImpl.
@@ -440,7 +404,8 @@ public class PrepareContractionHierarchiesTest {
         // use fastest weighting in this test to be able to fine-tune some weights via the speed (see below)
         Weighting fastestWeighting = new FastestWeighting(carEncoder);
         CHProfile chProfile = CHProfile.nodeBased(fastestWeighting);
-        final GraphHopperStorage g = createGHStorage(chProfile);
+        g = createGHStorage(chProfile);
+        lg = g.getCHGraph();
         // the following graph reproduces the issue. note that we will use the node ids as ch levels, so there will
         // be a shortcut 3->2 visible at node 2 and another one 3->4 visible at node 3.
         // we will fine-tune the edge-speeds such that without the fix node 4 will be stalled and node 5 will not get
@@ -496,7 +461,6 @@ public class PrepareContractionHierarchiesTest {
                 return g.getNodes();
             }
         }).doWork();
-        CHGraph lg = g.getCHGraph(chProfile);
         assertEquals("there should be exactly two (bidirectional) shortcuts (2-3) and (3-4)", 2, lg.getEdges() - lg.getOriginalEdges());
 
         // insert virtual node and edges
@@ -538,7 +502,6 @@ public class PrepareContractionHierarchiesTest {
 
     @Test
     public void testCircleBug() {
-        GraphHopperStorage g = createGHStorage();
         //  /--1
         // -0--/
         //  |
@@ -558,8 +521,6 @@ public class PrepareContractionHierarchiesTest {
         // 0-1->-2--3--4
         //   \-<-/
         //
-        GraphHopperStorage g = createGHStorage();
-        CHGraph lg = g.getCHGraph();
         g.edge(1, 2, 1, false);
         g.edge(2, 1, 1, false);
 
@@ -626,7 +587,7 @@ public class PrepareContractionHierarchiesTest {
         CHProfile bikeProfile = CHProfile.nodeBased(new ShortestWeighting(tmpBikeEncoder));
 
         List<CHProfile> profiles = Arrays.asList(carProfile, bikeProfile);
-        GraphHopperStorage ghStorage = new GraphHopperStorage(profiles, dir, tmpEncodingManager, false).create(1000);
+        GraphHopperStorage ghStorage = new GraphBuilder(tmpEncodingManager).setCHProfiles(profiles).create();
         initShortcutsGraph(ghStorage);
 
         ghStorage.freeze();
@@ -645,11 +606,11 @@ public class PrepareContractionHierarchiesTest {
         CHProfile carProfile = CHProfile.nodeBased(new FastestWeighting(tmpCarEncoder));
         CHProfile bikeProfile = CHProfile.nodeBased(new FastestWeighting(tmpBikeEncoder));
 
-        List<CHProfile> profiles = Arrays.asList(carProfile, bikeProfile);
-        GraphHopperStorage ghStorage = new GraphHopperStorage(profiles, dir, tmpEncodingManager, false).create(1000);
+        GraphHopperStorage ghStorage = new GraphBuilder(tmpEncodingManager).setCHProfiles(carProfile, bikeProfile).create();
         initShortcutsGraph(ghStorage);
-        EdgeIteratorState edge = GHUtility.getEdge(ghStorage, 9, 14).
-                set(tmpBikeEncoder.getAccessEnc(), false).setReverse(tmpBikeEncoder.getAccessEnc(), false);
+        GHUtility.getEdge(ghStorage, 9, 14).
+                set(tmpBikeEncoder.getAccessEnc(), false).
+                setReverse(tmpBikeEncoder.getAccessEnc(), false);
 
         ghStorage.freeze();
 
@@ -665,9 +626,7 @@ public class PrepareContractionHierarchiesTest {
         EncodingManager em = EncodingManager.create(carFlagEncoder, motorCycleEncoder);
         CHProfile carProfile = CHProfile.nodeBased(new FastestWeighting(carFlagEncoder));
         CHProfile motorCycleProfile = CHProfile.nodeBased(new FastestWeighting(motorCycleEncoder));
-        Directory dir = new RAMDirectory();
-        GraphHopperStorage ghStorage = new GraphHopperStorage(Arrays.asList(carProfile, motorCycleProfile), dir, em, false);
-        ghStorage.create(1000);
+        GraphHopperStorage ghStorage = new GraphBuilder(em).setCHProfiles(carProfile, motorCycleProfile).create();
 
         int numNodes = 5_000;
         int numQueries = 100;
@@ -708,7 +667,7 @@ public class PrepareContractionHierarchiesTest {
         assertTrue("reusing node ordering should speed up ch contraction", timeMotorCycle < 0.5 * timeCar);
     }
 
-    void checkPath(GraphHopperStorage g, CHProfile p, int expShortcuts, double expDistance, IntIndexedContainer expNodes) {
+    private void checkPath(GraphHopperStorage g, CHProfile p, int expShortcuts, double expDistance, IntIndexedContainer expNodes) {
         CHGraph lg = g.getCHGraph(p);
         PrepareContractionHierarchies prepare = createPrepareContractionHierarchies(g, p);
         prepare.doWork();
diff --git a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java
index 31ccbdec5..5216b1cef 100644
--- a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java
+++ b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java
@@ -218,7 +218,7 @@ public class GraphHopperStorageTest extends AbstractGraphStorageTester {
     public void testIdentical() {
         GraphHopperStorage store = new GraphHopperStorage(new RAMDirectory(), encodingManager, true);
         assertEquals(store.getNodes(), store.getBaseGraph().getNodes());
-        assertEquals(store.getAllEdges().length(), store.getBaseGraph().getAllEdges().length());
+        assertEquals(store.getEdges(), store.getBaseGraph().getEdges());
     }
 
     @Test
diff --git a/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java b/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java
deleted file mode 100644
index 30314e2a3..000000000
--- a/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- *  Licensed to GraphHopper GmbH under one or more contributor
- *  license agreements. See the NOTICE file distributed with this work for
- *  additional information regarding copyright ownership.
- *
- *  GraphHopper GmbH licenses this file to you under the Apache License,
- *  Version 2.0 (the "License"); you may not use this file except in
- *  compliance with the License. You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package com.graphhopper.storage.index;
-
-import com.carrotsearch.hppc.IntSet;
-import com.graphhopper.coll.GHIntHashSet;
-import com.graphhopper.routing.ch.PrepareEncoder;
-import com.graphhopper.routing.util.EncodingManager;
-import com.graphhopper.routing.weighting.FastestWeighting;
-import com.graphhopper.storage.*;
-import com.graphhopper.util.CHEdgeIteratorState;
-import com.graphhopper.util.EdgeIteratorState;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Peter Karich
- */
-public class LocationIndexTreeCHTest extends LocationIndexTreeTest {
-    @Override
-    public LocationIndexTree createIndex(Graph g, int resolution) {
-        if (resolution < 0)
-            resolution = 500000;
-        return (LocationIndexTree) createIndexNoPrepare(g, resolution).prepareIndex();
-    }
-
-    @Override
-    public LocationIndexTree createIndexNoPrepare(Graph g, int resolution) {
-        Directory dir = new RAMDirectory(location);
-        LocationIndexTree tmpIdx = new LocationIndexTree(g, dir);
-        tmpIdx.setResolution(resolution);
-        return tmpIdx;
-    }
-
-    @Override
-    GraphHopperStorage createGHStorage(Directory dir, EncodingManager encodingManager, boolean is3D) {
-        return new GraphHopperStorage(Arrays.asList(CHProfile.nodeBased(new FastestWeighting(encodingManager.getEncoder("car")))), dir, encodingManager, is3D).
-                create(100);
-    }
-
-    @Test
-    public void testCHGraph() {
-        GraphHopperStorage ghStorage = createGHStorage(new RAMDirectory(), encodingManager, false);
-        CHGraph lg = ghStorage.getCHGraph();
-        // 0
-        // 1
-        // 2
-        //  3
-        //   4
-        NodeAccess na = ghStorage.getNodeAccess();
-        na.setNode(0, 1, 0);
-        na.setNode(1, 0.5, 0);
-        na.setNode(2, 0, 0);
-        na.setNode(3, -1, 1);
-        na.setNode(4, -2, 2);
-
-        EdgeIteratorState iter1 = ghStorage.edge(0, 1, 10, true);
-        EdgeIteratorState iter2 = ghStorage.edge(1, 2, 10, true);
-        EdgeIteratorState iter3 = ghStorage.edge(2, 3, 14, true);
-        EdgeIteratorState iter4 = ghStorage.edge(3, 4, 14, true);
-
-        // create shortcuts
-        ghStorage.freeze();
-        int flags = PrepareEncoder.getScDirMask();
-        int sc1 = addShortcut(lg, 0, 2, 0, iter1.getEdge(), iter2.getEdge(), flags);
-        int sc2 = addShortcut(lg, 2, 4, 0, iter3.getEdge(), iter4.getEdge(), flags);
-        addShortcut(lg, 0, 4, 0, sc1, sc2, flags);
-
-        LocationIndex index = createIndex(ghStorage, -1);
-        assertEquals(2, findID(index, 0, 0.5));
-    }
-
-    private int addShortcut(CHGraph lg, int from, int to, double weight, int skip1, int skip2, int direction) {
-        return lg.shortcut(from, to, direction, weight, skip1, skip2);
-    }
-
-    @Test
-    public void testSortHighLevelFirst() {
-        GraphHopperStorage g = createGHStorage(new RAMDirectory(), encodingManager, false);
-        final CHGraph lg = g.getCHGraph();
-        lg.getNodeAccess().ensureNode(4);
-        lg.setLevel(1, 10);
-        lg.setLevel(2, 30);
-        lg.setLevel(3, 20);
-
-        // nodes with high level should come first to be covered by lower level nodes
-        List<Integer> list = Arrays.asList(1, 2, 3);
-        Collections.sort(list, new Comparator<Integer>() {
-            @Override
-            public int compare(Integer o1, Integer o2) {
-                return lg.getLevel(o2) - lg.getLevel(o1);
-            }
-        });
-        assertEquals("[2, 3, 1]", list.toString());
-    }
-
-    @Test
-    public void testCHGraphBug() {
-        // 0
-        // |
-        // | X  2--3
-        // |
-        // 1
-
-        GraphHopperStorage g = createGHStorage(new RAMDirectory(), encodingManager, false);
-        NodeAccess na = g.getNodeAccess();
-        na.setNode(0, 1, 0);
-        na.setNode(1, 0, 0);
-        na.setNode(2, 0.5, 0.5);
-        na.setNode(3, 0.5, 1);
-        EdgeIteratorState iter1 = g.edge(1, 0, 100, true);
-        g.edge(2, 3, 100, true);
-
-        CHGraph lg = g.getCHGraph();
-        g.freeze();
-        lg.setLevel(0, 11);
-        lg.setLevel(1, 10);
-        // disconnect higher 0 from lower 1
-        lg.disconnect(lg.createEdgeExplorer(), iter1);
-
-        lg.setLevel(2, 12);
-        lg.setLevel(3, 13);
-        // disconnect higher 3 from lower 2
-        lg.disconnect(lg.createEdgeExplorer(), iter1);
-
-        LocationIndexTree index = createIndex(g, 100000);
-
-        // very close to 2, but should match the edge 0--1
-        GHIntHashSet set = new GHIntHashSet();
-        index.findNetworkEntries(0.51, 0.2, set, 0);
-        index.findNetworkEntries(0.51, 0.2, set, 1);
-        IntSet expectedSet = new GHIntHashSet();
-        expectedSet.add(1);
-        expectedSet.add(2);
-        assertEquals(expectedSet, set);
-
-        assertEquals(0, findID(index, 0.51, 0.2));
-        assertEquals(1, findID(index, 0.1, 0.1));
-        assertEquals(2, findID(index, 0.51, 0.51));
-        assertEquals(3, findID(index, 0.51, 1.1));
-    }
-}
diff --git a/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeTest.java b/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeTest.java
index 4e280b1ca..5b3e83034 100644
--- a/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeTest.java
+++ b/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeTest.java
@@ -30,7 +30,10 @@ import com.graphhopper.util.shapes.BBox;
 import com.graphhopper.util.shapes.GHPoint;
 import org.junit.Test;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 import static org.junit.Assert.*;
 
@@ -47,7 +50,7 @@ public class LocationIndexTreeTest extends AbstractLocationIndexTester {
         return (LocationIndexTree) createIndexNoPrepare(g, resolution).prepareIndex();
     }
 
-    public LocationIndexTree createIndexNoPrepare(Graph g, int resolution) {
+    private LocationIndexTree createIndexNoPrepare(Graph g, int resolution) {
         Directory dir = new RAMDirectory(location);
         LocationIndexTree tmpIDX = new LocationIndexTree(g, dir);
         tmpIDX.setResolution(resolution);
diff --git a/core/src/test/java/com/graphhopper/util/InstructionListTest.java b/core/src/test/java/com/graphhopper/util/InstructionListTest.java
index dcda7b3ca..3824d3d30 100644
--- a/core/src/test/java/com/graphhopper/util/InstructionListTest.java
+++ b/core/src/test/java/com/graphhopper/util/InstructionListTest.java
@@ -21,20 +21,26 @@ import com.carrotsearch.hppc.IntArrayList;
 import com.graphhopper.routing.Dijkstra;
 import com.graphhopper.routing.InstructionsFromEdges;
 import com.graphhopper.routing.Path;
-import com.graphhopper.routing.profiles.BooleanEncodedValue;
-import com.graphhopper.routing.profiles.Roundabout;
+import com.graphhopper.routing.profiles.EnumEncodedValue;
+import com.graphhopper.routing.profiles.RoadAccess;
+import com.graphhopper.routing.profiles.RoadEnvironment;
 import com.graphhopper.routing.util.CarFlagEncoder;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.util.TraversalMode;
+import com.graphhopper.routing.weighting.FastestWeighting;
 import com.graphhopper.routing.weighting.ShortestWeighting;
+import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphBuilder;
 import com.graphhopper.storage.NodeAccess;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
 
 import static org.junit.Assert.assertEquals;
 
@@ -66,8 +72,7 @@ public class InstructionListTest {
         return list;
     }
 
-    @Test
-    public void testWayList() {
+    Graph createTestGraph() {
         Graph g = new GraphBuilder(carManager).create();
         // 0-1-2
         // | | |
@@ -112,10 +117,16 @@ public class InstructionListTest {
         list.add(1.0, 1.3);
         iter2.setName("8-9");
         iter2.setWayGeometry(list);
+        return g;
+    }
+
+    @Test
+    public void testWayList() {
+        Graph g = createTestGraph();
 
         ShortestWeighting weighting = new ShortestWeighting(carEncoder);
         Path p = new Dijkstra(g, weighting, TraversalMode.NODE_BASED).calcPath(0, 10);
-        InstructionList wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, trMap.getWithFallBack(Locale.US));
+        InstructionList wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
         List<String> tmpList = getTurnDescriptions(wayList);
         assertEquals(Arrays.asList("continue onto 0-1", "turn right onto 1-4", "turn left onto 7-8", "arrive at destination"),
                 tmpList);
@@ -144,7 +155,7 @@ public class InstructionListTest {
         assertEquals(42000, p.getDistance(), 1e-2);
         assertEquals(IntArrayList.from(6, 7, 8, 5, 2), p.calcNodes());
 
-        wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, trMap.getWithFallBack(Locale.US));
+        wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
         tmpList = getTurnDescriptions(wayList);
         assertEquals(Arrays.asList("continue onto 6-7", "turn left onto 5-8", "arrive at destination"),
                 tmpList);
@@ -154,9 +165,9 @@ public class InstructionListTest {
 
         // special case of identical start and end
         p = new Dijkstra(g, weighting, TraversalMode.NODE_BASED).calcPath(0, 0);
-        wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, trMap.getWithFallBack(Locale.US));
+        wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
         assertEquals(1, wayList.size());
-        assertEquals("arrive at destination", wayList.get(0).getTurnDescription(trMap.getWithFallBack(Locale.US)));
+        assertEquals("arrive at destination", wayList.get(0).getTurnDescription(usTR));
     }
 
     @Test
@@ -192,7 +203,7 @@ public class InstructionListTest {
 
         p = new Dijkstra(g, weighting, tMode).calcPath(3, 5);
         wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
-        tmpList = getTurnDescriptions( wayList);
+        tmpList = getTurnDescriptions(wayList);
         assertEquals(Arrays.asList("continue onto 3-4", "keep right onto 4-5", "arrive at destination"),
                 tmpList);
     }
@@ -225,7 +236,7 @@ public class InstructionListTest {
         ShortestWeighting weighting = new ShortestWeighting(carEncoder);
         Path p = new Dijkstra(g, weighting, tMode).calcPath(2, 3);
         InstructionList wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
-        List<String> tmpList = getTurnDescriptions( wayList);
+        List<String> tmpList = getTurnDescriptions(wayList);
         assertEquals(Arrays.asList("continue onto street", "turn right onto street", "arrive at destination"), tmpList);
     }
 
@@ -243,10 +254,10 @@ public class InstructionListTest {
         //     4  1
 
         NodeAccess na = g.getNodeAccess();
-        na.setNode(1, 51.734514,9.225571);
-        na.setNode(2, 51.73458,9.225442);
-        na.setNode(3, 51.734643,9.22541);
-        na.setNode(4, 51.734451,9.225436);
+        na.setNode(1, 51.734514, 9.225571);
+        na.setNode(2, 51.73458, 9.225442);
+        na.setNode(3, 51.734643, 9.22541);
+        na.setNode(4, 51.734451, 9.225436);
         g.edge(1, 2, 10, true);
         g.edge(2, 3, 10, true);
         g.edge(2, 4, 10, true);
@@ -254,7 +265,7 @@ public class InstructionListTest {
         ShortestWeighting weighting = new ShortestWeighting(carEncoder);
         Path p = new Dijkstra(g, weighting, tMode).calcPath(1, 3);
         InstructionList wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
-        List<String> tmpList = getTurnDescriptions( wayList);
+        List<String> tmpList = getTurnDescriptions(wayList);
         assertEquals(Arrays.asList("continue", "arrive at destination"), tmpList);
     }
 
@@ -272,10 +283,10 @@ public class InstructionListTest {
         //            4
 
         NodeAccess na = g.getNodeAccess();
-        na.setNode(1, 48.748493,9.322455);
-        na.setNode(2, 48.748577,9.322152);
-        na.setNode(3, 48.748776,9.321889);
-        na.setNode(4, 48.74847,9.322299);
+        na.setNode(1, 48.748493, 9.322455);
+        na.setNode(2, 48.748577, 9.322152);
+        na.setNode(3, 48.748776, 9.321889);
+        na.setNode(4, 48.74847, 9.322299);
         g.edge(1, 2, 10, true);
         g.edge(2, 3, 10, true);
         g.edge(2, 4, 10, true);
@@ -283,7 +294,7 @@ public class InstructionListTest {
         ShortestWeighting weighting = new ShortestWeighting(carEncoder);
         Path p = new Dijkstra(g, weighting, tMode).calcPath(1, 3);
         InstructionList wayList = InstructionsFromEdges.calcInstructions(p, g, weighting, carManager, usTR);
-        List<String> tmpList = getTurnDescriptions( wayList);
+        List<String> tmpList = getTurnDescriptions(wayList);
         assertEquals(Arrays.asList("continue", "arrive at destination"), tmpList);
     }
 
@@ -336,13 +347,27 @@ public class InstructionListTest {
         assertEquals("3-4", wayList.find(15.099, 9.9, 1000).getName());
     }
 
-    private List<String> pick(String key, List<Map<String, Object>> instructionJson) {
-        List<String> list = new ArrayList<>();
-
-        for (Map<String, Object> json : instructionJson) {
-            list.add(json.get(key).toString());
-        }
-        return list;
+    @Test
+    public void simpleAnnotations() {
+        Graph graph = createTestGraph();
+
+        EnumEncodedValue<RoadEnvironment> roadEnvEnc = carManager.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
+        EnumEncodedValue<RoadAccess> roadAccessEnc = carManager.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class);
+        EdgeIteratorState edge1 = GHUtility.getEdge(graph, 7, 8);
+        edge1.set(roadEnvEnc, RoadEnvironment.FERRY);
+
+        EdgeIteratorState edge2 = GHUtility.getEdge(graph, 8, 9);
+        edge2.set(roadAccessEnc, RoadAccess.PRIVATE);
+
+        Weighting weighting = new FastestWeighting(carEncoder);
+        final InstructionList ways = new InstructionList(usTR);
+        InstructionsFromEdges instrFromEdges = new InstructionsFromEdges(graph, weighting, carManager, usTR, ways);
+        instrFromEdges.next(edge1, 0, EdgeIterator.NO_EDGE);
+        instrFromEdges.next(edge2, 1, edge1.getEdge());
+        instrFromEdges.finish();
+
+        assertEquals("take the ferry", ways.get(0).getAnnotation().getMessage());
+        assertEquals("private road", ways.get(1).getAnnotation().getMessage());
     }
 
     private void compare(List<List<Double>> expected, List<List<Double>> actual) {
@@ -351,9 +376,7 @@ public class InstructionListTest {
             List<Double> wasE = actual.get(i);
             for (int j = 0; j < e.size(); j++) {
                 assertEquals("at index " + i + " value index " + j + " and value " + e + " vs " + wasE + "\n" + "Expected: " + expected + "\n" + "Actual: " + actual
-                        , e.get(j),
-                        wasE.get(j),
-                        1e-5d);
+                        , e.get(j), wasE.get(j), 1e-5d);
             }
         }
     }
diff --git a/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/GraphExplorerTest.java b/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/GraphExplorerTest.java
index 4ece82507..440701ae4 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/GraphExplorerTest.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/GraphExplorerTest.java
@@ -107,7 +107,7 @@ public class GraphExplorerTest {
         d.set(pt.getAccessEnc(), true);
         d.set(foot.getAccessEnc(), true);
 
-        int edgeId = graph.getAllEdges().length();
+        int edgeId = graph.getEdges();
 
         GtfsStorage gtfsStorage = mock(GtfsStorage.class);
         RealtimeFeed realtimeFeed = mock(RealtimeFeed.class);
@@ -158,7 +158,7 @@ public class GraphExplorerTest {
         graph.getNodeAccess().setNode(5, 5.0, 5.0);
 
 
-        int edgeId = graph.getAllEdges().length();
+        int edgeId = graph.getEdges();
 
         GtfsStorage gtfsStorage = mock(GtfsStorage.class);
         RealtimeFeed realtimeFeed = mock(RealtimeFeed.class);
diff --git a/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/WrapperGraphTest.java b/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/WrapperGraphTest.java
index eb80b92d2..b2c8512fc 100644
--- a/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/WrapperGraphTest.java
+++ b/reader-gtfs/src/test/java/com/graphhopper/reader/gtfs/WrapperGraphTest.java
@@ -40,10 +40,10 @@ public class WrapperGraphTest {
     public void testEternalOffByOneError() {
         GraphHopperStorage graph = new GraphHopperStorage(new RAMDirectory("wurst"), encodingManager, false);
         assertEquals(0, graph.getNodes());
-        assertEquals(0, graph.getAllEdges().length());
+        assertEquals(0, graph.getEdges());
         WrapperGraph wrapperGraph = new WrapperGraph(graph, Collections.emptyList());
         assertEquals(0, wrapperGraph.getNodes());
-        assertEquals(0, wrapperGraph.getAllEdges().length());
+        assertEquals(0, wrapperGraph.getEdges());
     }
 
 }
diff --git a/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java b/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
index b21ab6a70..1bba8a9f0 100644
--- a/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
+++ b/reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
@@ -803,7 +803,7 @@ public class GraphHopperIT {
     public void testKremsCyclewayInstructionsWithWayTypeInfo() {
         String tmpOsmFile = DIR + "/krems.osm.gz";
         String tmpVehicle = "bike";
-        String tmpImportVehicles = "car,bike";
+        String tmpImportVehicles = "foot,bike";
         String tmpWeightCalcStr = "fastest";
 
         GraphHopper tmpHopper = new GraphHopperOSM().
@@ -816,14 +816,14 @@ public class GraphHopperIT {
 
         Translation tr = tmpHopper.getTranslationMap().getWithFallBack(Locale.US);
         GHResponse rsp = tmpHopper.route(new GHRequest(48.410987, 15.599492, 48.383419, 15.659294).
-                setAlgorithm(ASTAR).setVehicle(tmpVehicle).setWeighting(tmpWeightCalcStr));
-
+                setVehicle(tmpVehicle).setWeighting(tmpWeightCalcStr));
+        assertFalse(rsp.hasErrors());
         PathWrapper arsp = rsp.getBest();
         assertEquals(6932.2, arsp.getDistance(), .1);
-        assertEquals(105, arsp.getPoints().getSize());
+        assertEquals(106, arsp.getPoints().getSize());
 
         InstructionList il = arsp.getInstructions();
-        assertEquals(21, il.size());
+        assertEquals(22, il.size());
 
         assertEquals("continue onto Obere Landstraße", il.get(0).getTurnDescription(tr));
         assertEquals("get off the bike", il.get(0).getAnnotation().getMessage());
@@ -840,8 +840,16 @@ public class GraphHopperIT {
         assertEquals("keep left onto Austraße", il.get(11).getTurnDescription(tr));
         assertEquals("keep left onto Rechte Kremszeile", il.get(12).getTurnDescription(tr));
         //..
-        assertEquals("turn right onto Treppelweg", il.get(17).getTurnDescription(tr));
-        assertEquals("cycleway", il.get(17).getAnnotation().getMessage());
+        assertEquals("turn right onto Treppelweg", il.get(18).getTurnDescription(tr));
+        assertEquals("cycleway", il.get(18).getAnnotation().getMessage());
+
+        // do not return 'get off bike' for foot
+        rsp = tmpHopper.route(new GHRequest(48.410987, 15.599492, 48.411172, 15.600371).
+                setAlgorithm(ASTAR).setVehicle("foot").setWeighting(tmpWeightCalcStr));
+        assertFalse(rsp.hasErrors());
+        il = rsp.getBest().getInstructions();
+        assertEquals("continue onto Obere Landstraße", il.get(0).getTurnDescription(tr));
+        assertEquals("", il.get(0).getAnnotation().getMessage());
     }
 
     @Test
diff --git a/reader-osm/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java b/reader-osm/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
index c3274ddd6..9baefff03 100644
--- a/reader-osm/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
+++ b/reader-osm/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
@@ -383,7 +383,7 @@ public class GraphHopperOSMTest {
         instance.importOrLoad();
 
         assertEquals(5, instance.getGraphHopperStorage().getNodes());
-        assertEquals(8, instance.getGraphHopperStorage().getAllEdges().length());
+        assertEquals(8, instance.getGraphHopperStorage().getEdges());
 
         // A to D
         GHResponse grsp = instance.route(new GHRequest(11.1, 50, 11.3, 51).setVehicle("car"));
diff --git a/web/src/test/java/com/graphhopper/http/resources/RouteResourceTest.java b/web/src/test/java/com/graphhopper/http/resources/RouteResourceTest.java
index a9b917335..7603fcd1c 100644
--- a/web/src/test/java/com/graphhopper/http/resources/RouteResourceTest.java
+++ b/web/src/test/java/com/graphhopper/http/resources/RouteResourceTest.java
@@ -31,6 +31,7 @@ import com.graphhopper.routing.profiles.Surface;
 import com.graphhopper.util.CmdArgs;
 import com.graphhopper.util.Helper;
 import com.graphhopper.util.InstructionList;
+import com.graphhopper.util.Parameters;
 import com.graphhopper.util.details.PathDetail;
 import com.graphhopper.util.exceptions.PointOutOfBoundsException;
 import com.graphhopper.util.shapes.GHPoint;
@@ -114,20 +115,6 @@ public class RouteResourceTest {
         assertTrue("There should be an error " + json.get("message"), json.get("message").asText().contains("Cannot parse point '1234'"));
     }
 
-    @Test
-    public void testQueryWithDirections() {
-        // Note, in general specifying directions does not work with CH, but this is an example where it works
-        final Response response = app.client().target("http://localhost:8080/route?" + "point=42.496696,1.499323&point=42.497257,1.501501&heading=240&heading=240&ch.force_heading=true").request().buildGet().invoke();
-        assertEquals(200, response.getStatus());
-        JsonNode json = response.readEntity(JsonNode.class);
-        JsonNode infoJson = json.get("info");
-        assertFalse(infoJson.has("errors"));
-        JsonNode path = json.get("paths").get(0);
-        double distance = path.get("distance").asDouble();
-        assertTrue("distance wasn't correct:" + distance, distance > 960);
-        assertTrue("distance wasn't correct:" + distance, distance < 970);
-    }
-
     @Test
     public void testQueryWithoutInstructions() {
         final Response response = app.client().target("http://localhost:8080/route?point=42.554851,1.536198&point=42.510071,1.548128&instructions=false").request().buildGet().invoke();
@@ -142,17 +129,25 @@ public class RouteResourceTest {
     }
 
     @Test
-    public void testQueryWithStraightVia() {
-        // Note, in general specifying pass_through does not work with CH, but this is an example where it works
+    public void testCHWithHeading_error() {
+        // There are special cases where heading works with node-based CH, but generally it leads to wrong results -> we expect an error
+        final Response response = app.client().target("http://localhost:8080/route?" + "point=42.496696,1.499323&point=42.497257,1.501501&heading=240&heading=240").request().buildGet().invoke();
+        assertEquals(400, response.getStatus());
+        JsonNode json = response.readEntity(JsonNode.class);
+        assertTrue("There should have been an error response", json.has("message"));
+        String expected = "The 'heading' parameter is currently not supported for speed mode, you need to disable speed mode with `ch.disable=true`. See issue #483";
+        assertTrue("There should be an error containing " + expected + ", but got: " + json.get("message"), json.get("message").asText().contains(expected));
+    }
+
+    @Test
+    public void testCHWithPassThrough_error() {
+        // There are special cases where pass_through works with node-based CH, but generally it leads to wrong results -> we expect an error
         final Response response = app.client().target("http://localhost:8080/route?point=42.534133,1.581473&point=42.534781,1.582149&point=42.535042,1.582514&pass_through=true").request().buildGet().invoke();
-        assertEquals(200, response.getStatus());
+        assertEquals(400, response.getStatus());
         JsonNode json = response.readEntity(JsonNode.class);
-        JsonNode infoJson = json.get("info");
-        assertFalse(infoJson.has("errors"));
-        JsonNode path = json.get("paths").get(0);
-        double distance = path.get("distance").asDouble();
-        assertTrue("distance wasn't correct:" + distance, distance > 320);
-        assertTrue("distance wasn't correct:" + distance, distance < 325);
+        assertTrue("There should have been an error response", json.has("message"));
+        String expected = "The '" + Parameters.Routing.PASS_THROUGH + "' parameter is currently not supported for speed mode, you need to disable speed mode with `ch.disable=true`. See issue #1765";
+        assertTrue("There should be an error containing " + expected + ", but got: " + json.get("message"), json.get("message").asText().contains(expected));
     }
 
     @Test