Repository: graphhopper/graphhopper
Pull request #711 (2016-04-29 15:33:37)

Reproducing & fixing reverse speed error
This fixes the bug in #665. The work to find this was done in #703.

This bug could be reproduced also for `bike2` which is very strange as I've never seen this failing in 'real world'.

The important part now is to set the flags for both speeds explicitly via
```java
flags = handleSpeed(way, ferrySpeed, flags);
```

or in motorcycle encoder via setSpeed&setReverseSpeed.

This is explicitly mentioned now in the create-new-flagencoder.md guide but the whole process should be made easier later on too.

karussell: Ah, before merging: I'll have to move the OSMReader independent test to a bike2 graph-only test. Just for clarity...

Patch:
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index a6c26c54f..635b7174b 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -4,4 +4,3 @@ Before creating an issue make sure to read our [contributing guide](https://gith
 
 The best way to get help about an GraphHopper issue is to create a valid and detailed issue content, preferable with a unit or integration test reproducing the issue. Please include the version of GraphHopper, the JVM and the operating system are you using and in case of a routing problem include a link to [GraphHopper Maps](https://graphhopper.com/maps/). Also tell us your expected routing result via additional markers and screenshots.
 
-If you have an Android application using GraphHopper, please **always** post to the [forum](https://discuss.graphhopper.com/c/graphhopper/graphhopper-ios-and-android) before and include logs and the version of your Android.
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index bbdea00bb..66aa5bf79 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,11 +1,11 @@
 [Members](https://github.com/graphhopper?tab=members) and [Contributors](https://github.com/graphhopper/graphhopper/contributors)
 
- * ammagamma, improvements like #700
+ * ammagamma, several improvements like #700, #703
  * AnahitaS, docs for Android, Android, Tomcat
  * andreaswolf, flag encoder versioning and more
  * agouge, discussion and API refactoring
  * b3nn0, Android improvements
- * boldtrn, motorcycle and improvements like conditional tag parsing etc
+ * boldtrn, motorcycle and improvements like conditional tag parsing, round trips and a lot more
  * cgarreau, increase of routing success rate via subnetwork cleanup
  * ChristianSeitzer, motorcycle improvements
  * daisy1754, fixed usage of graphhopper.sh script
diff --git a/android/app/src/main/java/com/graphhopper/android/MainActivity.java b/android/app/src/main/java/com/graphhopper/android/MainActivity.java
index b059edfa5..2a10bea4a 100644
--- a/android/app/src/main/java/com/graphhopper/android/MainActivity.java
+++ b/android/app/src/main/java/com/graphhopper/android/MainActivity.java
@@ -435,7 +435,7 @@ public class MainActivity extends Activity
             protected Path saveDoInBackground( Void... v ) throws Exception
             {
                 GraphHopper tmpHopp = new GraphHopper().forMobile();
-                tmpHopp.load(new File(mapsFolder, currentArea).getAbsolutePath() + "-gh");
+                tmpHopp.load(new File(mapsFolder, currentArea).getAbsolutePath());
                 log("found graph " + tmpHopp.getGraphHopperStorage().toString() + ", nodes:" + tmpHopp.getGraphHopperStorage().getNodes());
                 hopper = tmpHopp;
                 return null;
diff --git a/android/build.gradle b/android/build.gradle
index 2639588a2..ea13b3570 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -4,7 +4,7 @@ buildscript {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.1.0'
+        classpath 'com.android.tools.build:gradle:2.0.0'
     }
 }
 
diff --git a/android/gradle.properties b/android/gradle.properties
deleted file mode 100644
index 7f722e5f4..000000000
--- a/android/gradle.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-# Project-wide Gradle settings.
-
-# IDE (e.g. Android Studio) users:
-# Gradle settings configured through the IDE *will override*
-# any settings specified in this file.
-
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-# Default value: -Xmx10248m -XX:MaxPermSize=256m
-# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
-org.gradle.jvmargs=-Xmx2048m
-
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
\ No newline at end of file
diff --git a/config-example.properties b/config-example.properties
index cfa8c774e..1e1ced385 100644
--- a/config-example.properties
+++ b/config-example.properties
@@ -1,7 +1,8 @@
 ##### Vehicles #####
-
+#
 # Possible options: car,foot,bike,bike2,mtb,racingbike,motorcycle (comma separated)
-# bike2 takes elevation data into account (like up-hill is slower than down-hill) and requires enabling graph.elevation.provider below
+# bike2 takes elevation data into account (like up-hill is slower than down-hill)
+# and requires enabling graph.elevation.provider below
 graph.flagEncoders=car
 
 # Enable turn restrictions for car or motorcycle. 
@@ -9,63 +10,50 @@ graph.flagEncoders=car
 # graph.flagEncoders=car|turnCosts=true
 
 
-
 ##### Elevation #####
-
-# To populate your graph with elevation data use SRTM, default is noop (no elevation)
+#
+# To populate your graph with elevation data use SRTM, default is noop
 # graph.elevation.provider=srtm
-
+#
 # default location for cache is /tmp/srtm
 # graph.elevation.cachedir=./srtmprovider/
-
+#
 # If you have a slow disk or plenty of RAM change the default MMAP to:
 # graph.elevation.dataaccess=RAM_STORE
 
 
 
-#### Speed-up mode vs. flexibility mode ####
+##### Storage #####
+#
+# configure the memory access, use RAM_STORE for well equipped servers, 
+# MMAP_STORE_SYNC could be used otherwise but will be a lot slower
+graph.dataaccess=RAM_STORE
+
+# if you don't need turn instruction, you can reduce storage size by not storing way names:
+# osmreader.instructions=false
+
+# will write way names in the preferred language (language code as defined in ISO 639-1 or ISO 639-2):
+# osmreader.preferred-language=en
 
+#### Speed-up Mode vs. Flexibility Mode ####
+#
 # By default the speed-up mode with the 'fastest' weighting is used. Internally a graph preparation via
-# contraction hierarchies (CH) is done to speed routing up. This requires more RAM/disc space for holding the
+# contraction hierarchies is done to speed routing up. This requires more RAM/disc space for holding the
 # graph but less for every request. You can also setup multiple weightings, by providing a coma separated list.
-prepare.chWeightings=fastest
-
-# Disable the speed-up mode. Should be use only with routing.maxVisitedNodes
+# prepare.chWeightings=fastest
+#
+# Disable the speed-up mode (contraction hierarchies, CH) via enabling the flexibility mode:
 # prepare.chWeightings=no
-
-# To make preparation faster for multiple flagEncoders you can increase the default threads if you have enough RAM.
-# Change this setting only if you know what you are doing and if the default worked for you and really make sure you have enough RAM!
+#
+# To make preparation faster for multiple flagEncoders you can increase the default threads if you have enough RAM
 # prepare.threads=1
 
-
-
 ##### Routing #####
-
 # You can define the maximum visited nodes when routing. This may result in not found connections if there is no
-# connection between two points wihtin the given visited nodes. The default is Integer.MAX_VALUE. Useful for flexibility mode
-# routing.maxVisitedNodes = 1000000
-
-# If enabled, allows a user to run flexibility requests even if speed-up mode is enabled. Every request then has to include a hint routing.flexibleMode.force=true.
-# Attention, non-CH route calculations take way more time and resources, compared to CH routing.
-# A possible attacker might exploit this to slow down your service. Only enable it if you need it and with routing.maxVisitedNodes
-# routing.flexibleMode.allowed=true
-
-
+# connection between two points wihtin the given visited nodes. The default is Integer.MAX_VALUE.
+# routing.maxVisitedNodes = 10000
 
 ##### Web #####
-
-# if you want to support jsonp response type you need to add it explicitely here. By default it is disabled for stronger security.
+# if you want to support jsonp response type you need to add it explicitely here. By default it is disabled for 
+# stronger security.
 # web.jsonpAllowed=true
-
-
-
-##### Storage #####
-#
-# configure the memory access, use RAM_STORE for well equipped servers (default and recommended) or MMAP_STORE_SYNC
-graph.dataaccess=RAM_STORE
-
-# if you don't need turn instruction, you can reduce storage size by not storing way names:
-# osmreader.instructions=false
-
-# will write way names in the preferred language (language code as defined in ISO 639-1 or ISO 639-2):
-# osmreader.preferred-language=en
diff --git a/core/files/changelog.txt b/core/files/changelog.txt
index 0ea8f51c8..10189b9d7 100644
--- a/core/files/changelog.txt
+++ b/core/files/changelog.txt
@@ -1,8 +1,5 @@
-0.7    
-    use prepare.chWeightings instead of prepare.chWeighting e.g. for disabling CH use prepare.chWeightings=no
-    GraphHopper class is refactored regarding RoutingAlgorithmFactory in order to fix problem when integrating flexibility routing, most of the CH related stuff is moved into CHAlgoFactoryDecorator, several methods are deprecated to use the methods of the decorator, see #631
-    WeightingMap is now named HintsMap
-    use the correct graphHopperFolder as no automatic fallback to 'folder-gh' is happening anymore, see #704
+0.7
+    refactored FlagEncoder.handleFerryWay to getFerrySpeed to make it possible to fix #665
     removed setWeightLimit as too unspecific for arbitrary weights, use setMaxVisitedNodes instead
     missing renames for Path.setEdgeEntry -> setSPTEntry and AbstractAlgorithm.createEdgeEntry -> createSPTEntry
 
diff --git a/core/src/main/java/com/graphhopper/GHRequest.java b/core/src/main/java/com/graphhopper/GHRequest.java
index e8a93b2ac..8b3bcee77 100644
--- a/core/src/main/java/com/graphhopper/GHRequest.java
+++ b/core/src/main/java/com/graphhopper/GHRequest.java
@@ -17,7 +17,7 @@
  */
 package com.graphhopper;
 
-import com.graphhopper.routing.util.HintsMap;
+import com.graphhopper.routing.util.WeightingMap;
 import com.graphhopper.util.Helper;
 import com.graphhopper.util.shapes.GHPoint;
 
@@ -37,7 +37,8 @@ public class GHRequest
 {
     private String algo = "";
     private final List<GHPoint> points;
-    private final HintsMap hints = new HintsMap();
+    private final WeightingMap hints = new WeightingMap();
+    private String vehicle = "";
     private boolean possibleToAdd = false;
     private Locale locale = Locale.US;
 
@@ -250,13 +251,14 @@ public class GHRequest
      */
     public GHRequest setVehicle( String vehicle )
     {
-        hints.setVehicle(vehicle);
+        if (vehicle != null)
+            this.vehicle = vehicle;
         return this;
     }
 
     public String getVehicle()
     {
-        return hints.getVehicle();
+        return vehicle;
     }
 
     @Override
@@ -276,7 +278,7 @@ public class GHRequest
         return res + "(" + algo + ")";
     }
 
-    public HintsMap getHints()
+    public WeightingMap getHints()
     {
         return hints;
     }
diff --git a/core/src/main/java/com/graphhopper/GraphHopper.java b/core/src/main/java/com/graphhopper/GraphHopper.java
index bf978d65f..b1398fed3 100644
--- a/core/src/main/java/com/graphhopper/GraphHopper.java
+++ b/core/src/main/java/com/graphhopper/GraphHopper.java
@@ -23,7 +23,6 @@ import com.graphhopper.reader.dem.CGIARProvider;
 import com.graphhopper.reader.dem.ElevationProvider;
 import com.graphhopper.reader.dem.SRTMProvider;
 import com.graphhopper.routing.*;
-import com.graphhopper.routing.ch.CHAlgoFactoryDecorator;
 import com.graphhopper.routing.ch.PrepareContractionHierarchies;
 import com.graphhopper.routing.util.*;
 import com.graphhopper.storage.*;
@@ -39,9 +38,13 @@ import java.io.File;
 import java.io.IOException;
 import java.text.DateFormat;
 import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Easy to use access point to configure import and (offline) routing.
+ * <p>
  *
  * @author Peter Karich
  * @see GraphHopperAPI
@@ -67,7 +70,7 @@ public class GraphHopper implements GraphHopperAPI
     // for routing
     private boolean simplifyResponse = true;
     private TraversalMode traversalMode = TraversalMode.NODE_BASED;
-    private final Set<RoutingAlgorithmFactoryDecorator> algoDecorators = new LinkedHashSet<>();
+    private final Map<Weighting, RoutingAlgorithmFactory> algoFactories = new LinkedHashMap<Weighting, RoutingAlgorithmFactory>();
     private int maxVisitedNodes = Integer.MAX_VALUE;
     // for index
     private LocationIndex locationIndex;
@@ -77,7 +80,16 @@ public class GraphHopper implements GraphHopperAPI
     private int minNetworkSize = 200;
     private int minOneWayNetworkSize = 0;
     // for CH prepare    
-    private final CHAlgoFactoryDecorator chFactoryDecorator = new CHAlgoFactoryDecorator();
+    private boolean doPrepare = true;
+    private boolean chEnabled = true;
+    private final List<String> chWeightingList = new ArrayList<String>(Arrays.asList("fastest"));
+    private int chPrepareThreads = -1;
+    private ExecutorService chPreparePool;
+    private int preparePeriodicUpdates = -1;
+    private int prepareLazyUpdates = -1;
+    private int prepareNeighborUpdates = -1;
+    private int prepareContractedNodes = -1;
+    private double prepareLogMessages = -1;
     // for OSM import
     private String osmFile;
     private double osmReaderWayPointMaxDistance = 1;
@@ -89,8 +101,7 @@ public class GraphHopper implements GraphHopperAPI
 
     public GraphHopper()
     {
-        chFactoryDecorator.setEnabled(true);
-        algoDecorators.add(chFactoryDecorator);
+        setCHPrepareThreads(1);
     }
 
     /**
@@ -247,6 +258,7 @@ public class GraphHopper implements GraphHopperAPI
      * Only valid option for in-memory graph and if you e.g. want to disable store on flush for unit
      * tests. Specify storeOnFlush to true if you want that existing data will be loaded FROM disc
      * and all in-memory data will be flushed TO disc after flush is called e.g. while OSM import.
+     * <p>
      *
      * @param storeOnFlush true by default
      */
@@ -282,9 +294,19 @@ public class GraphHopper implements GraphHopperAPI
 
     /**
      * Wrapper method for {@link GraphHopper#setCHWeightings(List)}
-     *
-     * @deprecated Use getCHFactoryDecorator().setWeightingsAsStrings() instead. Will be removed in
-     * 0.8.
+     * <p>
+     * @deprecated This method is used as a deprecated wrapper to not break the JavaApi. This will
+     * be removed in the future. Please use {@link GraphHopper#setCHWeightings(List)} or
+     * {@link GraphHopper#setCHWeightings(String...)}
+     */
+    @Deprecated
+    public GraphHopper setCHWeighting( String weightingName )
+    {
+        return this.setCHWeightings(weightingName);
+    }
+
+    /**
+     * Wrapper method for {@link GraphHopper#setCHWeightings(List)}
      */
     public GraphHopper setCHWeightings( String... weightingNames )
     {
@@ -297,74 +319,72 @@ public class GraphHopper implements GraphHopperAPI
      *
      * @param weightingList A list containing multiple weightings like: "fastest", "shortest" or
      * your own weight-calculation type.
-     *
-     * @deprecated Use getCHFactoryDecorator().setWeightingsAsStrings() instead. Will be removed in
-     * 0.8.
      */
     public GraphHopper setCHWeightings( List<String> weightingList )
     {
         ensureNotLoaded();
-        chFactoryDecorator.setWeightingsAsStrings(weightingList);
+
+        if (weightingList.isEmpty())
+            throw new IllegalArgumentException("It is not allowed to pass an emtpy weightingList");
+
+        this.chWeightingList.clear();
+        for (String weight : weightingList)
+        {
+            weight = weight.toLowerCase();
+            weight = weight.trim();
+            this.chWeightingList.add(weight);
+        }
         return this;
     }
 
     /**
      * Returns all CHWeighting names
-     *
-     * @deprecated Use getCHFactoryDecorator().getWeightingsAsStrings() instead. Will be removed in
-     * 0.8.
      */
     public List<String> getCHWeightings()
     {
-        return chFactoryDecorator.getWeightingsAsStrings();
+        if (this.chWeightingList.isEmpty())
+            throw new IllegalStateException("Potential bug: chWeightingList is empty");
+
+        return this.chWeightingList;
     }
 
     /**
      * This method changes the number of threads used for preparation on import. Default is 1. Make
      * sure that you have enough memory to increase this number!
-     *
-     * @deprecated Use getCHFactoryDecorator().setCHPrepareThreads() instead. Will be removed in
-     * 0.8.
      */
     public GraphHopper setCHPrepareThreads( int prepareThreads )
     {
-        chFactoryDecorator.setPreparationThreads(prepareThreads);
+        this.chPrepareThreads = prepareThreads;
+        this.chPreparePool = java.util.concurrent.Executors.newFixedThreadPool(chPrepareThreads);
         return this;
     }
 
-    /**
-     * @deprecated Use getCHFactoryDecorator().getCHPrepareThreads() instead. Will be removed in
-     * 0.8.
-     */
     public int getCHPrepareThreads()
     {
-        return chFactoryDecorator.getPreparationThreads();
+        return chPrepareThreads;
     }
 
     /**
-     *
-     * @deprecated Use setEnabled() instead. Will be removed in 0.8.
+     * Disables the "CH-preparation" preparation only. Use only if you know what you do. To disable
+     * the full usage of CH use setCHEnable(false) instead.
      */
-    public GraphHopper setCHEnable( boolean enable )
+    @Deprecated
+    public GraphHopper setDoPrepare( boolean doPrepare )
     {
-        return setCHEnabled(enable);
+        this.doPrepare = doPrepare;
+        return this;
     }
 
     /**
      * Enables or disables contraction hierarchies (CH). This speed-up mode is enabled by default.
      */
-    public GraphHopper setCHEnabled( boolean enable )
+    public GraphHopper setCHEnable( boolean enable )
     {
         ensureNotLoaded();
-        chFactoryDecorator.setEnabled(enable);
+        chEnabled = enable;
         return this;
     }
 
-    public final boolean isCHEnabled()
-    {
-        return chFactoryDecorator.isEnabled();
-    }
-
     /**
      * This methods stops the algorithm from searching further if the resulting path would go over
      * the specified node count, important if CH is disabled.
@@ -374,6 +394,11 @@ public class GraphHopper implements GraphHopperAPI
         this.maxVisitedNodes = maxVisitedNodes;
     }
 
+    public boolean isCHEnabled()
+    {
+        return chEnabled;
+    }
+
     /**
      * @return true if storing and fetching elevation data is enabled. Default is false
      */
@@ -486,6 +511,7 @@ public class GraphHopper implements GraphHopperAPI
 
     /**
      * The underlying graph used in algorithms.
+     * <p>
      *
      * @throws IllegalStateException if graph is not instantiated.
      */
@@ -510,6 +536,7 @@ public class GraphHopper implements GraphHopperAPI
 
     /**
      * The location index created from the graph.
+     * <p>
      *
      * @throws IllegalStateException if index is not initialized
      */
@@ -619,8 +646,25 @@ public class GraphHopper implements GraphHopperAPI
         minNetworkSize = args.getInt("prepare.minNetworkSize", minNetworkSize);
         minOneWayNetworkSize = args.getInt("prepare.minOneWayNetworkSize", minOneWayNetworkSize);
 
-        // prepare CH
-        chFactoryDecorator.init(args);
+        // prepare CH        
+        doPrepare = args.getBool("prepare.doPrepare", doPrepare);
+        setCHPrepareThreads(args.getInt("prepare.threads", chPrepareThreads));
+
+        String chWeightingsStr = args.get("prepare.chWeightings", "");
+        // remove when deprecated setCHWeighting method is removed
+        if (chWeightingsStr.isEmpty())
+            chWeightingsStr = args.get("prepare.chWeighting", "fastest");
+
+        List<String> tmpCHWeightingList = Arrays.asList(chWeightingsStr.split(","));
+        chEnabled = !"no".equals(chWeightingsStr);
+        if (chEnabled)
+            setCHWeightings(tmpCHWeightingList);
+
+        preparePeriodicUpdates = args.getInt("prepare.updates.periodic", preparePeriodicUpdates);
+        prepareLazyUpdates = args.getInt("prepare.updates.lazy", prepareLazyUpdates);
+        prepareNeighborUpdates = args.getInt("prepare.updates.neighbor", prepareNeighborUpdates);
+        prepareContractedNodes = args.getInt("prepare.contracted-nodes", prepareContractedNodes);
+        prepareLogMessages = args.getDouble("prepare.logmessages", prepareLogMessages);
 
         // osm import
         osmReaderWayPointMaxDistance = args.getDouble("osmreader.wayPointMaxDistance", osmReaderWayPointMaxDistance);
@@ -742,6 +786,7 @@ public class GraphHopper implements GraphHopperAPI
 
     /**
      * Opens existing graph.
+     * <p>
      *
      * @param graphHopperFolder is the folder containing graphhopper files (which can be compressed
      * too)
@@ -755,7 +800,7 @@ public class GraphHopper implements GraphHopperAPI
         return initializeStorage(graphHopperFolder);
     }
 
-    private boolean initializeStorage( String graphHopperFolder )
+    private boolean initializeStorage(String graphHopperFolder)
     {
         if (Helper.isEmpty(graphHopperFolder))
             throw new IllegalStateException("graphHopperLocation is not specified. call init before");
@@ -800,15 +845,12 @@ public class GraphHopper implements GraphHopperAPI
         GHDirectory dir = new GHDirectory(ghLocation, dataAccessType);
         GraphExtension ext = encodingManager.needsTurnCostsSupport()
                 ? new TurnCostExtension() : new GraphExtension.NoOpExtension();
-
-        if (chFactoryDecorator.isEnabled())
+        if (chEnabled)
         {
-            initCHAlgoFactoryDecorator();
-            ghStorage = new GraphHopperStorage(chFactoryDecorator.getWeightings(), dir, encodingManager, hasElevation(), ext);
+            initCHAlgoFactories();
+            ghStorage = new GraphHopperStorage(new ArrayList<Weighting>(algoFactories.keySet()), dir, encodingManager, hasElevation(), ext);
         } else
-        {
             ghStorage = new GraphHopperStorage(dir, encodingManager, hasElevation(), ext);
-        }
 
         ghStorage.setSegmentSize(defaultSegmentSize);
 
@@ -838,52 +880,58 @@ public class GraphHopper implements GraphHopperAPI
         }
     }
 
-    public RoutingAlgorithmFactory getAlgorithmFactory( HintsMap map )
+    public RoutingAlgorithmFactory getAlgorithmFactory( Weighting weighting )
     {
-        RoutingAlgorithmFactory routingAlgorithmFactory = new RoutingAlgorithmFactorySimple();
-        for (RoutingAlgorithmFactoryDecorator decorator : algoDecorators)
-        {
-            if (decorator.isEnabled())
-                routingAlgorithmFactory = decorator.getDecoratedAlgorithmFactory(routingAlgorithmFactory, map);
-        }
+        RoutingAlgorithmFactory raf = algoFactories.get(weighting);
+        if (raf == null)
+            putAlgorithmFactory(weighting, raf = new RoutingAlgorithmFactorySimple());
 
-        return routingAlgorithmFactory;
+        return raf;
     }
 
-    public GraphHopper addAlgorithmFactoryDecorator( RoutingAlgorithmFactoryDecorator algoFactoryDecorator )
+    public Collection<RoutingAlgorithmFactory> getAlgorithmFactories()
     {
-        if (!algoDecorators.add(algoFactoryDecorator))
-            throw new IllegalArgumentException("Decorator was already added " + algoFactoryDecorator.getClass());
-
-        return this;
+        return algoFactories.values();
     }
 
-    public final CHAlgoFactoryDecorator getCHFactoryDecorator()
+    public GraphHopper putAlgorithmFactory( Weighting weighting, RoutingAlgorithmFactory algoFactory )
     {
-        return chFactoryDecorator;
+        algoFactories.put(weighting, algoFactory);
+        return this;
     }
 
-    private void initCHAlgoFactoryDecorator()
+    private void initCHAlgoFactories()
     {
-        if (!chFactoryDecorator.hasWeightings())
+        if (algoFactories.isEmpty())
             for (FlagEncoder encoder : encodingManager.fetchEdgeEncoders())
             {
-                for (String chWeightingStr : chFactoryDecorator.getWeightingsAsStrings())
+                for (String chWeightingStr : getCHWeightings())
                 {
-                    Weighting weighting = createWeighting(new HintsMap(chWeightingStr), encoder);
-                    chFactoryDecorator.addWeighting(weighting);
+                    Weighting weighting = createWeighting(new WeightingMap(chWeightingStr), encoder);
+                    algoFactories.put(weighting, null);
                 }
             }
     }
 
-    /**
-     * This method creates prepations.
-     *
-     * @deprecated use getCHFactoryDecorator().createPreparations() instead. Will be removed in 0.8.
-     */
     protected void createCHPreparations()
     {
-        chFactoryDecorator.createPreparations(ghStorage, traversalMode);
+        if (algoFactories.isEmpty())
+            throw new IllegalStateException("No algorithm factories found. Call load before?");
+
+        Set<Weighting> orderedSet = new LinkedHashSet<Weighting>(algoFactories.keySet());
+        algoFactories.clear();
+        for (Weighting weighting : orderedSet)
+        {
+            PrepareContractionHierarchies tmpPrepareCH = new PrepareContractionHierarchies(
+                    new GHDirectory("", DAType.RAM_INT), ghStorage, ghStorage.getGraph(CHGraph.class, weighting),
+                    weighting.getFlagEncoder(), weighting, traversalMode);
+            tmpPrepareCH.setPeriodicUpdates(preparePeriodicUpdates).
+                    setLazyUpdates(prepareLazyUpdates).
+                    setNeighborUpdates(prepareNeighborUpdates).
+                    setLogMessages(prepareLogMessages);
+
+            algoFactories.put(weighting, tmpPrepareCH);
+        }
     }
 
     /**
@@ -905,7 +953,7 @@ public class GraphHopper implements GraphHopperAPI
         }
 
         initLocationIndex();
-        if (chFactoryDecorator.isEnabled())
+        if (chEnabled)
             createCHPreparations();
 
         if (!isPrepared())
@@ -921,14 +969,15 @@ public class GraphHopper implements GraphHopperAPI
      * Based on the weightingParameters and the specified vehicle a Weighting instance can be
      * created. Note that all URL parameters are available in the weightingParameters as String if
      * you use the GraphHopper Web module.
+     * <p>
      *
      * @param weightingMap all parameters influencing the weighting. E.g. parameters coming via
      * GHRequest.getHints or directly via "&amp;api.xy=" from the URL of the web UI
      * @param encoder the required vehicle
      * @return the weighting to be used for route calculation
-     * @see HintsMap
+     * @see WeightingMap
      */
-    public Weighting createWeighting( HintsMap weightingMap, FlagEncoder encoder )
+    public Weighting createWeighting( WeightingMap weightingMap, FlagEncoder encoder )
     {
         String weighting = weightingMap.getWeighting().toLowerCase();
 
@@ -952,6 +1001,22 @@ public class GraphHopper implements GraphHopperAPI
         throw new UnsupportedOperationException("weighting " + weighting + " not supported");
     }
 
+    public Weighting getWeightingForCH( WeightingMap weightingMap, FlagEncoder encoder )
+    {
+        // get requested weighting name
+        String weightingStr = weightingMap.getWeighting().toLowerCase();
+        if (weightingStr.isEmpty())
+            weightingStr = getCHWeightings().get(0);
+
+        for (Weighting w : algoFactories.keySet())
+        {
+            if (w.matches(weightingStr, encoder))
+                return w;
+        }
+
+        throw new IllegalStateException("No weighting found for request " + weightingMap + ", encoder:" + encoder + ", " + algoFactories);
+    }
+
     /**
      * Potentially wraps the specified weighting into a TurnWeighting instance.
      */
@@ -978,13 +1043,9 @@ public class GraphHopper implements GraphHopperAPI
         if (ghStorage.isClosed())
             throw new IllegalStateException("You need to create a new GraphHopper instance as it is already closed");
 
-        // default handling
         String vehicle = request.getVehicle();
         if (vehicle.isEmpty())
-        {
             vehicle = getDefaultVehicle().toString();
-            request.setVehicle(vehicle);
-        }
 
         if (!encodingManager.supports(vehicle))
         {
@@ -1013,37 +1074,26 @@ public class GraphHopper implements GraphHopperAPI
         if (ghRsp.hasErrors())
             return Collections.emptyList();
 
-        RoutingAlgorithmFactory tmpAlgoFactory = getAlgorithmFactory(request.getHints());
         Weighting weighting;
         Graph routingGraph = ghStorage;
-
-        boolean forceFlexibleMode = request.getHints().getBool(CHAlgoFactoryDecorator.FORCE_FLEXIBLE_ROUTING, false);
-        if (!chFactoryDecorator.isForcingFlexibleModeAllowed() && forceFlexibleMode)
-        {
-            ghRsp.addError(new IllegalStateException("Flexible mode not enabled on the server-side"));
-            return Collections.emptyList();
-        }
-
-        if (chFactoryDecorator.isEnabled() && !forceFlexibleMode)
+        if (chEnabled)
         {
-            boolean forceCHHeading = request.getHints().getBool(CHAlgoFactoryDecorator.FORCE_HEADING, false);
+            boolean forceCHHeading = request.getHints().getBool("force_heading_ch", false);
             if (!forceCHHeading && request.hasFavoredHeading(0))
                 throw new IllegalStateException("Heading is not (fully) supported for CHGraph. See issue #483");
-
-            if (!(tmpAlgoFactory instanceof PrepareContractionHierarchies))
-                throw new IllegalStateException("Although CH was enabled a non-CH algorithm factory was returned " + tmpAlgoFactory);
-
-            weighting = ((PrepareContractionHierarchies) tmpAlgoFactory).getWeighting();
+            weighting = getWeightingForCH(request.getHints(), encoder);
             routingGraph = ghStorage.getGraph(CHGraph.class, weighting);
         } else
-        {
             weighting = createWeighting(request.getHints(), encoder);
-        }
 
+        RoutingAlgorithmFactory tmpAlgoFactory = getAlgorithmFactory(weighting);
         QueryGraph queryGraph = new QueryGraph(routingGraph);
         queryGraph.lookup(qResults);
         weighting = createTurnWeighting(weighting, queryGraph, encoder);
 
+        List<Path> altPaths = new ArrayList<Path>(points.size() - 1);
+        QueryResult fromQResult = qResults.get(0);
+
         int maxVisistedNodesForRequest = request.getHints().getInt("routing.maxVisitedNodes", maxVisitedNodes);
         if (maxVisistedNodesForRequest > maxVisitedNodes)
         {
@@ -1072,8 +1122,7 @@ public class GraphHopper implements GraphHopperAPI
 
         Locale locale = request.getLocale();
         Translation tr = trMap.getWithFallBack(locale);
-        List<Path> altPaths = new ArrayList<Path>(points.size() - 1);
-        QueryResult fromQResult = qResults.get(0);
+
         // Every alternative path makes one AltResponse BUT if via points exists then reuse the altResponse object
         PathWrapper altResponse = new PathWrapper();
         ghRsp.add(altResponse);
@@ -1217,16 +1266,59 @@ public class GraphHopper implements GraphHopperAPI
 
     protected void prepare()
     {
-        boolean tmpPrepare = chFactoryDecorator.isEnabled();
+        boolean tmpPrepare = doPrepare && chEnabled;
         if (tmpPrepare)
         {
             ensureWriteAccess();
 
-            if (chFactoryDecorator.getPreparationThreads() > 1 && dataAccessType.isMMap() && !dataAccessType.isSynched())
+            if (chPrepareThreads > 1 && dataAccessType.isMMap() && !dataAccessType.isSynched())
                 throw new IllegalStateException("You cannot execute CH preparation in parallel for MMAP without synching! Specify MMAP_SYNC or use 1 thread only");
 
             ghStorage.freeze();
-            chFactoryDecorator.prepare(ghStorage.getProperties());
+
+            int counter = 0;
+            for (final Entry<Weighting, RoutingAlgorithmFactory> entry : algoFactories.entrySet())
+            {
+                logger.info((++counter) + "/" + algoFactories.entrySet().size() + " calling prepare.doWork for " + entry.getKey() + " ... (" + Helper.getMemInfo() + ")");
+                if (!(entry.getValue() instanceof PrepareContractionHierarchies))
+                    throw new IllegalStateException("RoutingAlgorithmFactory is not suited for CH preparation " + entry.getValue());
+
+                final String name = AbstractWeighting.weightingToFileName(entry.getKey());
+                chPreparePool.execute(new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        String errorKey = "prepare.error." + name;
+                        try
+                        {
+                            ghStorage.getProperties().put(errorKey, "CH preparation incomplete");
+                            // toString is not taken into account so we need to cheat, see http://stackoverflow.com/q/6113746/194609 for other options                        
+                            Thread.currentThread().setName(name);
+                            PrepareContractionHierarchies pch = (PrepareContractionHierarchies) entry.getValue();
+                            pch.doWork();
+                            ghStorage.getProperties().put(errorKey, "");
+                            ghStorage.getProperties().put("prepare.date." + name, Helper.createFormatter().format(new Date()));
+                        } catch (Exception ex)
+                        {
+                            logger.error("Problem while CH preparation " + name, ex);
+                            ghStorage.getProperties().put(errorKey, ex.getMessage());
+                        }
+                    }
+                });
+            }
+
+            chPreparePool.shutdown();
+            try
+            {
+                if (!chPreparePool.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS))
+                    chPreparePool.shutdownNow();
+
+            } catch (InterruptedException ie)
+            {
+                chPreparePool.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
         }
         ghStorage.getProperties().put("prepare.done", tmpPrepare);
     }
diff --git a/core/src/main/java/com/graphhopper/reader/OSMTagParser.java b/core/src/main/java/com/graphhopper/reader/OSMTagParser.java
index 7d3406c5d..a1f550116 100644
--- a/core/src/main/java/com/graphhopper/reader/OSMTagParser.java
+++ b/core/src/main/java/com/graphhopper/reader/OSMTagParser.java
@@ -23,7 +23,7 @@ import javax.xml.datatype.Duration;
 
 /**
  * This class currently parses the duration tag only.
- *
+ * <p/>
  * @author ratrun
  */
 public class OSMTagParser
diff --git a/core/src/main/java/com/graphhopper/routing/AlternativeRoute.java b/core/src/main/java/com/graphhopper/routing/AlternativeRoute.java
index 765bb2c15..cee11fac4 100644
--- a/core/src/main/java/com/graphhopper/routing/AlternativeRoute.java
+++ b/core/src/main/java/com/graphhopper/routing/AlternativeRoute.java
@@ -44,7 +44,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 /**
  * This class implements the alternative paths search using the "plateau" and partially the
  * "penalty" method discribed in the following papers.
- * <p>
+ * <p/>
  * <ul>
  * <li>Choice Routing Explanation - Camvit 2009:
  * http://www.camvit.com/camvit-technical-english/Camvit-Choice-Routing-Explanation-english.pdf</li>
@@ -58,6 +58,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  * http://algo2.iti.kit.edu/download/altgraph_tapas_extended.pdf
  * </li>
  * </ul>
+ * <p/>
  *
  * @author Peter Karich
  */
diff --git a/core/src/main/java/com/graphhopper/routing/RoutingAlgorithm.java b/core/src/main/java/com/graphhopper/routing/RoutingAlgorithm.java
index 7019638cd..ce18f75eb 100644
--- a/core/src/main/java/com/graphhopper/routing/RoutingAlgorithm.java
+++ b/core/src/main/java/com/graphhopper/routing/RoutingAlgorithm.java
@@ -30,14 +30,14 @@ public interface RoutingAlgorithm
 {
     /**
      * Calculates the best path between the specified nodes.
-     *
+     * <p/>
      * @return the path. Call the method found() to make sure that the path is valid.
      */
     Path calcPath( int from, int to );
 
     /**
      * Calculates multiple possibilities for a path.
-     *
+     * <p/>
      * @see #calcPath(int, int)
      */
     List<Path> calcPaths( int from, int to );
diff --git a/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactory.java b/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactory.java
index c19897b3e..675ed6481 100644
--- a/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactory.java
@@ -20,8 +20,6 @@ package com.graphhopper.routing;
 import com.graphhopper.storage.Graph;
 
 /**
- * This interface manages RoutingAlgorithm creation.
- *
  * @author Peter Karich
  */
 public interface RoutingAlgorithmFactory
diff --git a/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactoryDecorator.java b/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactoryDecorator.java
deleted file mode 100644
index 58769113b..000000000
--- a/core/src/main/java/com/graphhopper/routing/RoutingAlgorithmFactoryDecorator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Licensed to GraphHopper and Peter Karich under one or more contributor
- *  license agreements. See the NOTICE file distributed with this work for 
- *  additional information regarding copyright ownership.
- *
- *  GraphHopper 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.routing;
-
-import com.graphhopper.routing.util.HintsMap;
-
-/**
- *
- * @author Peter Karich
- */
-public interface RoutingAlgorithmFactoryDecorator
-{
-    boolean isEnabled();
-
-    /**
-     * This method returns the specified algoFactory unchanged, decorates it or completely replaces
-     * it depending on the specified optionsMap.
-     */
-    RoutingAlgorithmFactory getDecoratedAlgorithmFactory( RoutingAlgorithmFactory algoFactory, HintsMap optionsMap );
-}
diff --git a/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java b/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java
deleted file mode 100644
index 7a070a810..000000000
--- a/core/src/main/java/com/graphhopper/routing/ch/CHAlgoFactoryDecorator.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- *  Licensed to GraphHopper and Peter Karich under one or more contributor
- *  license agreements. See the NOTICE file distributed with this work for 
- *  additional information regarding copyright ownership.
- *
- *  GraphHopper 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.routing.ch;
-
-import com.graphhopper.GraphHopper;
-import com.graphhopper.routing.RoutingAlgorithmFactory;
-import com.graphhopper.routing.RoutingAlgorithmFactoryDecorator;
-import com.graphhopper.routing.util.AbstractWeighting;
-import com.graphhopper.routing.util.HintsMap;
-import com.graphhopper.routing.util.TraversalMode;
-import com.graphhopper.routing.util.Weighting;
-import com.graphhopper.storage.*;
-import com.graphhopper.util.CmdArgs;
-import com.graphhopper.util.Helper;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class implements the CH decorator for the routing algorithm factory and provides several
- * helper methods related to CH preparation and its vehicle profiles.
- *
- * @author Peter Karich
- */
-public class CHAlgoFactoryDecorator implements RoutingAlgorithmFactoryDecorator
-{
-    /**
-     * The property name in HintsMap if CH routing should be ignored.
-     */
-    public static final String FORCE_FLEXIBLE_ROUTING = "routing.flexibleMode.force";
-    /**
-     * The property name in HintsMap if heading should be used for CH regardless of the possible
-     * routing errors.
-     */
-    public static final String FORCE_HEADING = "force_heading_ch";
-
-    private final Logger logger = LoggerFactory.getLogger(getClass());
-    private final List<PrepareContractionHierarchies> preparations = new ArrayList<>();
-    // we need to decouple weighting objects from the weighting list of strings 
-    // as we need the strings to create the GraphHopperStorage and the GraphHopperStorage to create the preparations from the Weighting objects currently requiring the encoders
-    private final List<Weighting> weightings = new ArrayList<>();
-    private final List<String> weightingsAsStrings = new ArrayList<>();
-    private boolean forcingFlexibleModeAllowed = false;
-    // for backward compatibility enable CH by default.
-    private boolean enabled = true;
-    private int preparationThreads;
-    private ExecutorService chPreparePool;
-    private int preparationPeriodicUpdates = -1;
-    private int preparationLazyUpdates = -1;
-    private int preparationNeighborUpdates = -1;
-    private int preparationContractedNodes = -1;
-    private double preparationLogMessages = -1;
-
-    public CHAlgoFactoryDecorator()
-    {
-        setPreparationThreads(1);
-        setWeightingsAsStrings(Arrays.asList(getDefaultWeighting()));
-    }
-
-    public void init( CmdArgs args )
-    {
-        setPreparationThreads(args.getInt("prepare.threads", getPreparationThreads()));
-
-        String deprecatedWeightingConfig = args.get("prepare.chWeighting", "");
-        if (!deprecatedWeightingConfig.isEmpty())
-            throw new IllegalStateException("Use prepare.chWeightings and a comma separated list instead of prepare.chWeighting");
-
-        // default is enabled & fastest
-        boolean enableThis = isEnabled();
-        String chWeightingsStr = args.get("prepare.chWeightings", "");
-        if ("no".equals(chWeightingsStr))
-        {
-            enableThis = false;
-        } else if (!chWeightingsStr.isEmpty())
-        {
-            List<String> tmpCHWeightingList = Arrays.asList(chWeightingsStr.split(","));
-            setWeightingsAsStrings(tmpCHWeightingList);
-            enableThis = true;
-        }
-
-        setEnabled(enableThis);
-        if (enableThis)
-            setForcingFlexibleModeAllowed(args.getBool("routing.flexibleMode.allowed", isForcingFlexibleModeAllowed()));
-
-        setPreparationPeriodicUpdates(args.getInt("prepare.updates.periodic", getPreparationPeriodicUpdates()));
-        setPreparationLazyUpdates(args.getInt("prepare.updates.lazy", getPreparationLazyUpdates()));
-        setPreparationNeighborUpdates(args.getInt("prepare.updates.neighbor", getPreparationNeighborUpdates()));
-        setPreparationContractedNodes(args.getInt("prepare.contracted-nodes", getPreparationContractedNodes()));
-        setPreparationLogMessages(args.getDouble("prepare.logmessages", getPreparationLogMessages()));
-    }
-
-    public CHAlgoFactoryDecorator setPreparationPeriodicUpdates( int preparePeriodicUpdates )
-    {
-        this.preparationPeriodicUpdates = preparePeriodicUpdates;
-        return this;
-    }
-
-    public int getPreparationPeriodicUpdates()
-    {
-        return preparationPeriodicUpdates;
-    }
-
-    public CHAlgoFactoryDecorator setPreparationContractedNodes( int prepareContractedNodes )
-    {
-        this.preparationContractedNodes = prepareContractedNodes;
-        return this;
-    }
-
-    public int getPreparationContractedNodes()
-    {
-        return preparationContractedNodes;
-    }
-
-    public CHAlgoFactoryDecorator setPreparationLazyUpdates( int prepareLazyUpdates )
-    {
-        this.preparationLazyUpdates = prepareLazyUpdates;
-        return this;
-    }
-
-    public int getPreparationLazyUpdates()
-    {
-        return preparationLazyUpdates;
-    }
-
-    public CHAlgoFactoryDecorator setPreparationLogMessages( double prepareLogMessages )
-    {
-        this.preparationLogMessages = prepareLogMessages;
-        return this;
-    }
-
-    public double getPreparationLogMessages()
-    {
-        return preparationLogMessages;
-    }
-
-    public CHAlgoFactoryDecorator setPreparationNeighborUpdates( int prepareNeighborUpdates )
-    {
-        this.preparationNeighborUpdates = prepareNeighborUpdates;
-        return this;
-    }
-
-    public int getPreparationNeighborUpdates()
-    {
-        return preparationNeighborUpdates;
-    }
-
-    /**
-     * Enables or disables contraction hierarchies (CH). This speed-up mode is enabled by default.
-     */
-    public final void setEnabled( boolean enabled )
-    {
-        this.enabled = enabled;
-    }
-
-    public final boolean isEnabled()
-    {
-        return enabled;
-    }
-
-    /**
-     * This method specifies if although the CH preparation is enabled a 'more expensive' flexible
-     * request can be made via routing hints.
-     */
-    public final CHAlgoFactoryDecorator setForcingFlexibleModeAllowed( boolean forcingFlexibleModeAllowed )
-    {
-        this.forcingFlexibleModeAllowed = forcingFlexibleModeAllowed;
-        return this;
-    }
-
-    public final boolean isForcingFlexibleModeAllowed()
-    {
-        return forcingFlexibleModeAllowed;
-    }
-
-    /**
-     * Decouple weightings from PrepareContractionHierarchies as we need weightings for the
-     * graphstorage and the graphstorage for the preparation.
-     */
-    public CHAlgoFactoryDecorator addWeighting( Weighting weighting )
-    {
-        weightings.add(weighting);
-        return this;
-    }
-
-    public CHAlgoFactoryDecorator addWeighting( String weighting )
-    {
-        weightingsAsStrings.add(weighting);
-        return this;
-    }
-
-    public CHAlgoFactoryDecorator addPreparation( PrepareContractionHierarchies pch )
-    {
-        preparations.add(pch);
-        int lastIndex = preparations.size() - 1;
-        if (lastIndex >= weightings.size())
-            throw new IllegalStateException("Cannot access weighting for PrepareContractionHierarchies with " + pch.getWeighting()
-                    + ". Call add(Weighting) before");
-
-        if (preparations.get(lastIndex).getWeighting() != weightings.get(lastIndex))
-            throw new IllegalArgumentException("Weighting of PrepareContractionHierarchies " + preparations.get(lastIndex).getWeighting()
-                    + " needs to be identical to previously added " + weightings.get(lastIndex));
-        return this;
-    }
-
-    public final boolean hasWeightings()
-    {
-        return !weightings.isEmpty();
-    }
-
-    public final List<Weighting> getWeightings()
-    {
-        return weightings;
-    }
-
-    public CHAlgoFactoryDecorator setWeightingsAsStrings( String... weightingNames )
-    {
-        return setWeightingsAsStrings(Arrays.asList(weightingNames));
-    }
-
-    /**
-     * Enables the use of contraction hierarchies to reduce query times. Enabled by default.
-     *
-     * @param weightingList A list containing multiple weightings like: "fastest", "shortest" or
-     * your own weight-calculation type.
-     */
-    public CHAlgoFactoryDecorator setWeightingsAsStrings( List<String> weightingList )
-    {
-        if (weightingList.isEmpty())
-            throw new IllegalArgumentException("It is not allowed to pass an emtpy weightingList");
-
-        weightingsAsStrings.clear();
-        for (String strWeighting : weightingList)
-        {
-            strWeighting = strWeighting.toLowerCase();
-            strWeighting = strWeighting.trim();
-            addWeighting(strWeighting);
-        }
-        return this;
-    }
-
-    public List<String> getWeightingsAsStrings()
-    {
-        if (this.weightingsAsStrings.isEmpty())
-            throw new IllegalStateException("Potential bug: chWeightingList is empty");
-
-        return this.weightingsAsStrings;
-    }
-
-    private String getDefaultWeighting()
-    {
-        return weightingsAsStrings.isEmpty() ? "fastest" : weightingsAsStrings.get(0);
-    }
-
-    public List<PrepareContractionHierarchies> getPreparations()
-    {
-        return preparations;
-    }
-
-    @Override
-    public RoutingAlgorithmFactory getDecoratedAlgorithmFactory( RoutingAlgorithmFactory defaultAlgoFactory, HintsMap map )
-    {
-        boolean forceFlexMode = map.getBool(FORCE_FLEXIBLE_ROUTING, false);
-        if (!isEnabled() || forceFlexMode)
-            return defaultAlgoFactory;
-
-        if (preparations.isEmpty())
-            throw new IllegalStateException("No preparations added to this decorator");
-
-        if (map.getWeighting().isEmpty())
-            map.setWeighting(getDefaultWeighting());
-
-        for (PrepareContractionHierarchies p : preparations)
-        {
-            if (p.getWeighting().matches(map))
-                return p;
-        }
-
-        throw new IllegalStateException("Cannot find RoutingAlgorithmFactory for weighting map " + map);
-    }
-
-    /**
-     * This method changes the number of threads used for preparation on import. Default is 1. Make
-     * sure that you have enough memory to increase this number!
-     */
-    public void setPreparationThreads( int preparationThreads )
-    {
-        this.preparationThreads = preparationThreads;
-        this.chPreparePool = java.util.concurrent.Executors.newFixedThreadPool(preparationThreads);
-    }
-
-    public int getPreparationThreads()
-    {
-        return preparationThreads;
-    }
-
-    public void prepare( final StorableProperties properties )
-    {
-        int counter = 0;
-        for (final PrepareContractionHierarchies prepare : getPreparations())
-        {
-            logger.info((++counter) + "/" + getPreparations().size() + " calling prepare.doWork for " + prepare.getWeighting() + " ... (" + Helper.getMemInfo() + ")");
-            final String name = AbstractWeighting.weightingToFileName(prepare.getWeighting());
-            chPreparePool.execute(new Runnable()
-            {
-                @Override
-                public void run()
-                {
-                    String errorKey = "prepare.error." + name;
-                    try
-                    {
-                        properties.put(errorKey, "CH preparation incomplete");
-                        // toString is not taken into account so we need to cheat, see http://stackoverflow.com/q/6113746/194609 for other options                        
-
-                        Thread.currentThread().setName(name);
-                        prepare.doWork();
-                        properties.put(errorKey, "");
-                        properties.put("prepare.date." + name, Helper.createFormatter().format(new Date()));
-                    } catch (Exception ex)
-                    {
-                        logger.error("Problem while CH preparation " + name, ex);
-                        properties.put(errorKey, ex.getMessage());
-                    }
-                }
-            });
-        }
-
-        chPreparePool.shutdown();
-        try
-        {
-            if (!chPreparePool.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS))
-                chPreparePool.shutdownNow();
-
-        } catch (InterruptedException ie)
-        {
-            chPreparePool.shutdownNow();
-            Thread.currentThread().interrupt();
-        }
-    }
-
-    public void createPreparations( GraphHopperStorage ghStorage, TraversalMode traversalMode )
-    {
-        if (!isEnabled() || !preparations.isEmpty())
-            return;
-        if (weightings.isEmpty())
-            throw new IllegalStateException("No CH weightings found");
-
-        for (Weighting weighting : getWeightings())
-        {
-            PrepareContractionHierarchies tmpPrepareCH = new PrepareContractionHierarchies(
-                    new GHDirectory("", DAType.RAM_INT), ghStorage, ghStorage.getGraph(CHGraph.class, weighting),
-                    weighting.getFlagEncoder(), weighting, traversalMode);
-            tmpPrepareCH.setPeriodicUpdates(preparationPeriodicUpdates).
-                    setLazyUpdates(preparationLazyUpdates).
-                    setNeighborUpdates(preparationNeighborUpdates).
-                    setLogMessages(preparationLogMessages);
-
-            addPreparation(tmpPrepareCH);
-        }
-    }
-}
diff --git a/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java b/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java
index c8b2076e8..451995dce 100644
--- a/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/ch/PreparationWeighting.java
@@ -20,7 +20,6 @@ package com.graphhopper.routing.ch;
 
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.routing.util.Weighting;
-import com.graphhopper.routing.util.HintsMap;
 import com.graphhopper.util.EdgeIteratorState;
 import com.graphhopper.util.CHEdgeIteratorState;
 
@@ -63,9 +62,9 @@ public class PreparationWeighting implements Weighting
     }
 
     @Override
-    public boolean matches( HintsMap map )
+    public boolean matches( String weightingAsStr, FlagEncoder encoder )
     {
-        return getName().equals(map.getWeighting()) && userWeighting.getFlagEncoder().toString().equals(map.getVehicle());
+        return userWeighting.getName().equals(weightingAsStr) && encoder == userWeighting.getFlagEncoder();
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
index c5519c918..bbefc5512 100644
--- a/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
@@ -475,7 +475,7 @@ public abstract class AbstractFlagEncoder implements FlagEncoder, TurnCostEncode
     /**
      * Special handling for ferry ways.
      */
-    protected long handleFerryTags( OSMWay way, double unknownSpeed, double shortTripsSpeed, double longTripsSpeed )
+    protected double getFerrySpeed( OSMWay way, double unknownSpeed, double shortTripsSpeed, double longTripsSpeed )
     {
         long duration = 0;
         try
@@ -511,8 +511,7 @@ public abstract class AbstractFlagEncoder implements FlagEncoder, TurnCostEncode
                             if (shortTripsSpeed > getMaxSpeed())
                                 shortTripsSpeed = getMaxSpeed();
                             longTripsSpeed = shortTripsSpeed;
-                        }
-                        else
+                        } else
                         {
                             // Now we set to the lowest possible still accessible speed. 
                             shortTripsSpeed = speedEncoder.factor / 2;
@@ -531,14 +530,14 @@ public abstract class AbstractFlagEncoder implements FlagEncoder, TurnCostEncode
         if (durationInHours == 0)
         {
             // unknown speed -> put penalty on ferry transport
-            return setSpeed(0, unknownSpeed);
+            return unknownSpeed;
         } else if (durationInHours > 1)
         {
             // lengthy ferries should be faster than short trip ferry
-            return setSpeed(0, longTripsSpeed);
+            return longTripsSpeed;
         } else
         {
-            return setSpeed(0, shortTripsSpeed);
+            return shortTripsSpeed;
         }
     }
 
@@ -655,11 +654,8 @@ public abstract class AbstractFlagEncoder implements FlagEncoder, TurnCostEncode
         {
             if (costs != 0 || Double.isInfinite(costs))
                 throw new IllegalArgumentException("Restricted turn can only have infinite costs (or use 0)");
-        } else
-        {
-            if (costs >= maxTurnCosts)
-                throw new IllegalArgumentException("Cost is too high. Or specifiy restricted == true");
-        }
+        } else if (costs >= maxTurnCosts)
+            throw new IllegalArgumentException("Cost is too high. Or specifiy restricted == true");
 
         if (costs < 0)
             throw new IllegalArgumentException("Turn costs cannot be negative");
@@ -750,7 +746,7 @@ public abstract class AbstractFlagEncoder implements FlagEncoder, TurnCostEncode
     /**
      * @param way: needed to retrieve OSM tags
      * @param speed: speed guessed e.g. from the road type or other tags
-     * @return The assumed speed. 
+     * @return The assumed speed.
      */
     protected double applyMaxSpeed( OSMWay way, double speed )
     {
diff --git a/core/src/main/java/com/graphhopper/routing/util/AbstractWeighting.java b/core/src/main/java/com/graphhopper/routing/util/AbstractWeighting.java
index ff10a29fd..2b632afd4 100644
--- a/core/src/main/java/com/graphhopper/routing/util/AbstractWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/util/AbstractWeighting.java
@@ -35,10 +35,9 @@ public abstract class AbstractWeighting implements Weighting
     }
 
     @Override
-    public boolean matches( HintsMap reqMap )
+    public boolean matches( String weightingAsStr, FlagEncoder encoder )
     {
-        return getName().equals(reqMap.getWeighting())
-                && flagEncoder.toString().equals(reqMap.getVehicle());
+        return getName().equals(weightingAsStr) && encoder == flagEncoder;
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java
index aabe14616..a6bdbb2ac 100644
--- a/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java
@@ -44,7 +44,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
     protected static final int PUSHING_SECTION_SPEED = 4;
     private long unpavedBit = 0;
     // Pushing section heighways are parts where you need to get off your bike and push it (German: Schiebestrecke)
-    protected final HashSet<String> pushingSectionsHighways = new HashSet<String>();
+    protected final HashSet<String> pushingSections = new HashSet<String>();
     protected final HashSet<String> oppositeLanes = new HashSet<String>();
     protected final Set<String> preferHighwayTags = new HashSet<String>();
     protected final Set<String> avoidHighwayTags = new HashSet<String>();
@@ -69,7 +69,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
     {
         super(speedBits, speedFactor, maxTurnCosts);
         // strict set, usually vehicle and agricultural/forestry are ignored by cyclists
-        restrictions.addAll(Arrays.asList("bicycle", "vehicle", "access"));
+        restrictions.addAll(Arrays.asList("bicycle", "access"));
         restrictedValues.add("private");
         restrictedValues.add("no");
         restrictedValues.add("restricted");
@@ -261,7 +261,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
             return 0;
 
         // use the way if it is tagged for bikes
-        if (way.hasTag("bicycle", intendedValues) || way.hasTag("bicycle", "dismount"))
+        if (way.hasTag("bicycle", intendedValues))
             return acceptBit;
 
         // accept only if explicitly tagged for bike usage
@@ -355,34 +355,35 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
         if (!isAccept(allowed))
             return 0;
 
-        long encoded = 0;
+        long flags = 0;
         double wayTypeSpeed = getSpeed(way);
         if (!isFerry(allowed))
         {
             wayTypeSpeed = applyMaxSpeed(way, wayTypeSpeed);
-            encoded = handleSpeed(way, wayTypeSpeed, encoded);
-            encoded = handleBikeRelated(way, encoded, relationFlags > UNCHANGED.getValue());
+            flags = handleSpeed(way, wayTypeSpeed, flags);
+            flags = handleBikeRelated(way, flags, relationFlags > UNCHANGED.getValue());
 
             boolean isRoundabout = way.hasTag("junction", "roundabout");
             if (isRoundabout)
             {
-                encoded = setBool(encoded, K_ROUNDABOUT, true);
+                flags = setBool(flags, K_ROUNDABOUT, true);
             }
 
         } else
         {
-            encoded = handleFerryTags(way,
+            double ferrySpeed = getFerrySpeed(way,
                     highwaySpeeds.get("living_street"),
                     highwaySpeeds.get("track"),
                     highwaySpeeds.get("primary"));
-            encoded |= directionBitMask;
+            flags = handleSpeed(way, ferrySpeed, flags);
+            flags |= directionBitMask;
         }
         int priorityFromRelation = 0;
         if (relationFlags != 0)
             priorityFromRelation = (int) relationCodeEncoder.getValue(relationFlags);
 
-        encoded = priorityWayEncoder.setValue(encoded, handlePriority(way, wayTypeSpeed, priorityFromRelation));
-        return encoded;
+        flags = priorityWayEncoder.setValue(flags, handlePriority(way, wayTypeSpeed, priorityFromRelation));
+        return flags;
     }
 
     int getSpeed( OSMWay way )
@@ -402,7 +403,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
                 if (highwaySpeed != null && surfaceSpeed > highwaySpeed)
                 {
                     // Avoid boosting if pushing section
-                    if (pushingSectionsHighways.contains(highwayTag))
+                    if (pushingSections.contains(highwayTag))
                         speed = highwaySpeed;
                     else
                         speed = surfaceSpeed;
@@ -428,13 +429,12 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
         // Until now we assumed that the way is no pushing section
         // Now we check, but only in case that our speed is bigger compared to the PUSHING_SECTION_SPEED
         if ((speed > PUSHING_SECTION_SPEED)
-                && (!way.hasTag("bicycle", intendedValues)))
+                && (!way.hasTag("bicycle", intendedValues) && way.hasTag("highway", pushingSections)))
         {
-            if (way.hasTag("highway", pushingSectionsHighways) 
-                    || way.hasTag("bicycle", "dismount"))
-            {
+            if (way.hasTag("highway", "steps"))
+                speed = PUSHING_SECTION_SPEED / 2;
+            else
                 speed = PUSHING_SECTION_SPEED;
-            }
         }
 
         return speed;
@@ -569,7 +569,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
                 weightToPrioMap.put(50d, AVOID_AT_ALL_COSTS.getValue());
         }
 
-        if (pushingSectionsHighways.contains(highway)
+        if (pushingSections.contains(highway)
                 || way.hasTag("bicycle", "use_sidepath")
                 || "parking_aisle".equals(service))
         {
@@ -680,7 +680,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
 
     boolean isPushingSection( OSMWay way )
     {
-        return way.hasTag("highway", pushingSectionsHighways) || way.hasTag("railway", "platform") || way.hasTag("bicycle", "dismount");
+        return way.hasTag("highway", pushingSections) || way.hasTag("railway", "platform");
     }
 
     protected long handleSpeed( OSMWay way, double speed, long encoded )
@@ -762,7 +762,7 @@ public class BikeCommonFlagEncoder extends AbstractFlagEncoder
 
     void addPushingSection( String highway )
     {
-        pushingSectionsHighways.add(highway);
+        pushingSections.add(highway);
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/BikeFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/BikeFlagEncoder.java
index 915a6fde0..e054be7b8 100644
--- a/core/src/main/java/com/graphhopper/routing/util/BikeFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/BikeFlagEncoder.java
@@ -84,7 +84,9 @@ public class BikeFlagEncoder extends BikeCommonFlagEncoder
     {
         String highway = way.getTag("highway");
         String trackType = way.getTag("tracktype");
-        return super.isPushingSection(way) || "track".equals(highway) && trackType != null && !"grade1".equals(trackType);
+        return way.hasTag("highway", pushingSections)
+                || way.hasTag("railway", "platform")
+                || "track".equals(highway) && trackType != null && !"grade1".equals(trackType);
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
index 6f4ad92d7..8154ea988 100644
--- a/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
@@ -243,7 +243,7 @@ public class CarFlagEncoder extends AbstractFlagEncoder
         if (!isAccept(allowed))
             return 0;
 
-        long encoded;
+        long flags = 0;
         if (!isFerry(allowed))
         {
             // get assumed speed from highway type
@@ -254,11 +254,11 @@ public class CarFlagEncoder extends AbstractFlagEncoder
             if (speed > 30 && way.hasTag("surface", badSurfaceSpeedMap))
                 speed = 30;
 
-            encoded = setSpeed(0, speed);
+            flags = setSpeed(flags, speed);
 
             boolean isRoundabout = way.hasTag("junction", "roundabout");
             if (isRoundabout)
-                encoded = setBool(encoded, K_ROUNDABOUT, true);
+                flags = setBool(flags, K_ROUNDABOUT, true);
 
             boolean isOneway = way.hasTag("oneway", oneways)
                     || way.hasTag("vehicle:backward")
@@ -272,19 +272,20 @@ public class CarFlagEncoder extends AbstractFlagEncoder
                         || way.hasTag("vehicle:forward", "no")
                         || way.hasTag("motor_vehicle:forward", "no");
                 if (isBackward)
-                    encoded |= backwardBit;
+                    flags |= backwardBit;
                 else
-                    encoded |= forwardBit;
+                    flags |= forwardBit;
             } else
-                encoded |= directionBitMask;
+                flags |= directionBitMask;
 
         } else
         {
-            encoded = handleFerryTags(way, defaultSpeedMap.get("living_street"), defaultSpeedMap.get("service"), defaultSpeedMap.get("residential"));
-            encoded |= directionBitMask;
+            double ferrySpeed = getFerrySpeed(way, defaultSpeedMap.get("living_street"), defaultSpeedMap.get("service"), defaultSpeedMap.get("residential"));
+            flags = setSpeed(flags, ferrySpeed);
+            flags |= directionBitMask;
         }
 
-        return encoded;
+        return flags;
     }
 
     public String getWayInfo( OSMWay way )
diff --git a/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
index 89c17e123..92a48329f 100644
--- a/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
@@ -73,7 +73,7 @@ public class FootFlagEncoder extends AbstractFlagEncoder
     public FootFlagEncoder( int speedBits, double speedFactor )
     {
         super(speedBits, speedFactor, 0);
-        restrictions.addAll(Arrays.asList("foot", "vehicle", "access"));
+        restrictions.addAll(Arrays.asList("foot", "access"));
         restrictedValues.add("private");
         restrictedValues.add("no");
         restrictedValues.add("restricted");
@@ -287,38 +287,39 @@ public class FootFlagEncoder extends AbstractFlagEncoder
         if (!isAccept(allowed))
             return 0;
 
-        long encoded = 0;
+        long flags = 0;
         if (!isFerry(allowed))
         {
             String sacScale = way.getTag("sac_scale");
             if (sacScale != null)
             {
                 if ("hiking".equals(sacScale))
-                    encoded = speedEncoder.setDoubleValue(encoded, MEAN_SPEED);
+                    flags = speedEncoder.setDoubleValue(flags, MEAN_SPEED);
                 else
-                    encoded = speedEncoder.setDoubleValue(encoded, SLOW_SPEED);
+                    flags = speedEncoder.setDoubleValue(flags, SLOW_SPEED);
             } else
             {
-                encoded = speedEncoder.setDoubleValue(encoded, MEAN_SPEED);
+                flags = speedEncoder.setDoubleValue(flags, MEAN_SPEED);
             }
-            encoded |= directionBitMask;
+            flags |= directionBitMask;
 
             boolean isRoundabout = way.hasTag("junction", "roundabout");
             if (isRoundabout)
-                encoded = setBool(encoded, K_ROUNDABOUT, true);
+                flags = setBool(flags, K_ROUNDABOUT, true);
 
         } else
         {
-            encoded = encoded | handleFerryTags(way, SLOW_SPEED, MEAN_SPEED, FERRY_SPEED);
-            encoded |= directionBitMask;
+            double ferrySpeed = getFerrySpeed(way, SLOW_SPEED, MEAN_SPEED, FERRY_SPEED);
+            flags = setSpeed(flags, ferrySpeed);
+            flags |= directionBitMask;
         }
 
         int priorityFromRelation = 0;
         if (relationFlags != 0)
             priorityFromRelation = (int) relationCodeEncoder.getValue(relationFlags);
 
-        encoded = priorityWayEncoder.setValue(encoded, handlePriority(way, priorityFromRelation));
-        return encoded;
+        flags = priorityWayEncoder.setValue(flags, handlePriority(way, priorityFromRelation));
+        return flags;
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java
index 411d5faf0..7099a7d2b 100644
--- a/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java
@@ -208,7 +208,7 @@ public class MotorcycleFlagEncoder extends CarFlagEncoder
         if (!isAccept(allowed))
             return 0;
 
-        long encoded = 0;
+        long flags = 0;
         if (!isFerry(allowed))
         {
             // get assumed speed from highway type
@@ -225,39 +225,41 @@ public class MotorcycleFlagEncoder extends CarFlagEncoder
 
             boolean isRoundabout = way.hasTag("junction", "roundabout");
             if (isRoundabout)
-                encoded = setBool(0, K_ROUNDABOUT, true);
+                flags = setBool(0, K_ROUNDABOUT, true);
 
             if (way.hasTag("oneway", oneways) || isRoundabout)
             {
                 if (way.hasTag("oneway", "-1"))
                 {
-                    encoded = setReverseSpeed(encoded, speed);
-                    encoded |= backwardBit;
+                    flags = setReverseSpeed(flags, speed);
+                    flags |= backwardBit;
                 } else
                 {
-                    encoded = setSpeed(encoded, speed);
-                    encoded |= forwardBit;
+                    flags = setSpeed(flags, speed);
+                    flags |= forwardBit;
                 }
             } else
             {
-                encoded = setSpeed(encoded, speed);
-                encoded = setReverseSpeed(encoded, speed);
-                encoded |= directionBitMask;
+                flags = setSpeed(flags, speed);
+                flags = setReverseSpeed(flags, speed);
+                flags |= directionBitMask;
             }
 
         } else
         {
-            encoded = handleFerryTags(way, defaultSpeedMap.get("living_street"), defaultSpeedMap.get("service"), defaultSpeedMap.get("residential"));
-            encoded |= directionBitMask;
+            double ferrySpeed = getFerrySpeed(way, defaultSpeedMap.get("living_street"), defaultSpeedMap.get("service"), defaultSpeedMap.get("residential"));
+            flags = setSpeed(flags, ferrySpeed);
+            flags = setReverseSpeed(flags, ferrySpeed);
+            flags |= directionBitMask;
         }
 
         // relations are not yet stored -> see BikeCommonFlagEncoder.defineRelationBits how to do this
-        encoded = priorityWayEncoder.setValue(encoded, handlePriority(way, priorityFromRelation));
+        flags = priorityWayEncoder.setValue(flags, handlePriority(way, priorityFromRelation));
 
         // Set the curvature to the Maximum
-        encoded = curvatureEncoder.setValue(encoded, 10);
+        flags = curvatureEncoder.setValue(flags, 10);
 
-        return encoded;
+        return flags;
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/RacingBikeFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/RacingBikeFlagEncoder.java
index dfd67b753..b0d728685 100644
--- a/core/src/main/java/com/graphhopper/routing/util/RacingBikeFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/RacingBikeFlagEncoder.java
@@ -165,9 +165,8 @@ public class RacingBikeFlagEncoder extends BikeCommonFlagEncoder
     {
         String highway = way.getTag("highway");
         String trackType = way.getTag("tracktype");
-        return way.hasTag("highway", pushingSectionsHighways)
+        return way.hasTag("highway", pushingSections)
                 || way.hasTag("railway", "platform")
-                || way.hasTag("bicycle", "dismount")
                 || "track".equals(highway) && trackType != null && !"grade1".equals(trackType);
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java b/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java
index e12d293f9..0c7436b70 100644
--- a/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java
@@ -103,10 +103,10 @@ public class TurnWeighting implements Weighting
     }
 
     @Override
-    public boolean matches( HintsMap weightingMap )
+    public boolean matches( String weightingAsStr, FlagEncoder encoder )
     {
         // TODO without 'turn' in comparison
-        return superWeighting.matches(weightingMap);
+        return superWeighting.matches(weightingAsStr, encoder);
     }
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/Weighting.java b/core/src/main/java/com/graphhopper/routing/util/Weighting.java
index 81d96b4ad..565e96b93 100644
--- a/core/src/main/java/com/graphhopper/routing/util/Weighting.java
+++ b/core/src/main/java/com/graphhopper/routing/util/Weighting.java
@@ -51,5 +51,5 @@ public interface Weighting
     /**
      * Returns true if the specified weighting and encoder matches to this Weighting.
      */
-    boolean matches( HintsMap map );
+    boolean matches( String weightingAsStr, FlagEncoder encoder );
 }
diff --git a/core/src/main/java/com/graphhopper/routing/util/HintsMap.java b/core/src/main/java/com/graphhopper/routing/util/WeightingMap.java
similarity index 73%
rename from core/src/main/java/com/graphhopper/routing/util/HintsMap.java
rename to core/src/main/java/com/graphhopper/routing/util/WeightingMap.java
index 014d97e06..1df1e19c1 100644
--- a/core/src/main/java/com/graphhopper/routing/util/HintsMap.java
+++ b/core/src/main/java/com/graphhopper/routing/util/WeightingMap.java
@@ -22,9 +22,9 @@ import com.graphhopper.util.PMap;
 /**
  * @author Peter Karich
  */
-public class HintsMap extends PMap
+public class WeightingMap extends PMap
 {
-    public HintsMap()
+    public WeightingMap()
     {
     }
 
@@ -32,20 +32,20 @@ public class HintsMap extends PMap
      * Convenient constructor if only one parameter is provided
      * <p>
      */
-    public HintsMap( String weighting )
+    public WeightingMap( String weighting )
     {
         super(5);
         setWeighting(weighting);
     }
 
     @Override
-    public HintsMap put( String key, Object str )
+    public WeightingMap put( String key, Object str )
     {
         super.put(key, str);
         return this;
     }
 
-    public HintsMap setWeighting( String w )
+    public WeightingMap setWeighting( String w )
     {
         if (w != null)
             super.put("weighting", w);
@@ -54,18 +54,6 @@ public class HintsMap extends PMap
 
     public String getWeighting()
     {
-        return super.get("weighting", "").toLowerCase();
-    }
-
-    public HintsMap setVehicle( String v )
-    {
-        if (v != null)
-            super.put("vehicle", v);
-        return this;
-    }
-
-    public String getVehicle()
-    {
-        return super.get("vehicle", "").toLowerCase();
+        return super.get("weighting", "");
     }
 }
diff --git a/docs/core/create-new-flagencoder.md b/docs/core/create-new-flagencoder.md
index 2e5a49196..cfea45828 100644
--- a/docs/core/create-new-flagencoder.md
+++ b/docs/core/create-new-flagencoder.md
@@ -25,6 +25,7 @@ see Bike2WeightFlagEncoder for an example. You'll have to overwrite the followin
  * setProperties
  * reverseFlags
  * setLowSpeed
+ * always set reverse speed explicitely, see #665
 
 ## Elevation
 
diff --git a/graphhopper.sh b/graphhopper.sh
index 1b72b0881..51f5cdaf5 100755
--- a/graphhopper.sh
+++ b/graphhopper.sh
@@ -207,9 +207,7 @@ else
 fi
 
 if [ "$JAVA_OPTS" = "" ]; then
-  JAVA_OPTS="-Xmx1000m -Xms1000m -server -XX:+HeapDumpOnOutOfMemoryError"
-else
-  JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
+  JAVA_OPTS="-Xmx1000m -Xms1000m -server"
 fi
 
 
@@ -263,20 +261,20 @@ elif [ "$ACTION" = "miniui" ]; then
 
 
 elif [ "$ACTION" = "measurement" ]; then
- ARGS="config=$CONFIG graph.location=$GRAPH osmreader.osm=$OSM_FILE prepare.chWeighting=fastest graph.flagEncoders=CAR prepare.minNetworkSize=10000 prepare.minOnewayNetworkSize=10000"
- # echo -e "\ncreate graph via $ARGS, $JAR"
- # START=$(date +%s)
+ ARGS="config=$CONFIG graph.location=$GRAPH osmreader.osm=$OSM_FILE prepare.chWeighting=fastest graph.flagEncoders=CAR"
+ echo -e "\ncreate graph via $ARGS, $JAR"
+ START=$(date +%s)
  # avoid islands for measurement at all costs
- # "$JAVA" $JAVA_OPTS -cp "$JAR" $GH_CLASS $ARGS prepare.doPrepare=false prepare.minNetworkSize=10000 prepare.minOnewayNetworkSize=10000
- # END=$(date +%s)
- # IMPORT_TIME=$(($END - $START))
+ "$JAVA" $JAVA_OPTS -cp "$JAR" $GH_CLASS $ARGS prepare.doPrepare=false prepare.minNetworkSize=10000 prepare.minOnewayNetworkSize=10000
+ END=$(date +%s)
+ IMPORT_TIME=$(($END - $START))
 
  function startMeasurement {
     COUNT=5000
     commit_info=$(git log -n 1 --pretty=oneline)
     echo -e "\nperform measurement via jar=> $JAR and ARGS=> $ARGS"
     "$JAVA" $JAVA_OPTS -cp "$JAR" com.graphhopper.tools.Measurement $ARGS measurement.count=$COUNT measurement.location="$M_FILE_NAME" \
-            measurement.gitinfo="$commit_info"
+            graph.importTime=$IMPORT_TIME measurement.gitinfo="$commit_info"
  }
  
  
diff --git a/tools/src/main/java/com/graphhopper/tools/Measurement.java b/tools/src/main/java/com/graphhopper/tools/Measurement.java
index fa7314d7d..b623b4357 100644
--- a/tools/src/main/java/com/graphhopper/tools/Measurement.java
+++ b/tools/src/main/java/com/graphhopper/tools/Measurement.java
@@ -23,7 +23,6 @@ import com.graphhopper.GHResponse;
 import com.graphhopper.GraphHopper;
 import com.graphhopper.coll.GHBitSet;
 import com.graphhopper.coll.GHBitSetImpl;
-import com.graphhopper.reader.DataReader;
 import com.graphhopper.routing.AlgorithmOptions;
 import com.graphhopper.routing.RoutingAlgorithmFactorySimple;
 import com.graphhopper.routing.util.*;
@@ -61,11 +60,49 @@ public class Measurement
     private long seed;
     private int maxNode;
 
+    class MeasureHopper extends GraphHopper
+    {
+        @Override
+        protected void prepare()
+        {
+            // do nothing as we need normal graph first. in second step do it explicitely
+        }
+
+        @Override
+        protected void ensureNotLoaded()
+        {
+            // skip check. we know what we are doing
+        }
+
+        public void doPostProcessing( Weighting w )
+        {
+            // re-create index to avoid bug as pickNode in locationIndex.prepare could be wrong while indexing if level is not taken into account and assumed to be 0 for pre-initialized graph
+            StopWatch sw = new StopWatch().start();
+
+            // let algo routing factory convert simple to CH preparation
+            putAlgorithmFactory(w, null);
+            createCHPreparations();
+            super.prepare();
+
+            setLocationIndex(createLocationIndex(new RAMDirectory()));
+            put("prepare.time", sw.stop().getTime());
+            int edges = getGraphHopperStorage().getAllEdges().getMaxId();
+            int edgesAndShortcuts = getGraphHopperStorage().getGraph(CHGraph.class, w).getAllEdges().getMaxId();
+            put("prepare.shortcuts", edgesAndShortcuts - edges);
+        }
+    }
+
     // creates properties file in the format key=value
     // Every value is one y-value in a separate diagram with an identical x-value for every Measurement.start call
     void start( CmdArgs args )
     {
+        long importTook = args.getLong("graph.importTime", -1);
+        put("graph.importTime", importTook);
+
         String graphLocation = args.get("graph.location", "");
+        if (Helper.isEmpty(graphLocation))
+            throw new IllegalStateException("no graph.location specified");
+
         String propLocation = args.get("measurement.location", "");
         if (Helper.isEmpty(propLocation))
             propLocation = "measurement" + new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss").format(new Date()) + ".properties";
@@ -74,61 +111,43 @@ public class Measurement
         String gitCommit = args.get("measurement.gitinfo", "");
         int count = args.getInt("measurement.count", 5000);
 
-        GraphHopper hopper = new GraphHopper()
-        {
-            @Override
-            protected void prepare()
-            {
-                StopWatch sw = new StopWatch().start();
-                super.prepare();
-                put("prepare.time", sw.stop().getTime());
-                int edges = getGraphHopperStorage().getAllEdges().getMaxId();
-                Weighting weighting = getCHFactoryDecorator().getWeightings().get(0);
-                int edgesAndShortcuts = getGraphHopperStorage().getGraph(CHGraph.class, weighting).getAllEdges().getMaxId();
-                put("prepare.shortcuts", edgesAndShortcuts - edges);
-            }
-
-            @Override
-            protected DataReader importData() throws IOException
-            {
-                StopWatch sw = new StopWatch().start();
-                DataReader dr = super.importData();
-                put("graph.importTime", sw.stop().getSeconds());
-                return dr;
-            }
-        };
-
-        hopper.init(args);
-        hopper.getCHFactoryDecorator().setForcingFlexibleModeAllowed(true);
-        hopper.importOrLoad();
+        MeasureHopper hopper = new MeasureHopper();
+        hopper.forDesktop();
+        if (!hopper.load(graphLocation))
+            throw new IllegalStateException("Cannot load existing graph at " + graphLocation);
 
         GraphHopperStorage g = hopper.getGraphHopperStorage();
-//        if ("true".equals(g.getProperties().get("prepare.done")))
-//            throw new IllegalStateException("Graph has to be unprepared but wasn't!");
+        if ("true".equals(g.getProperties().get("prepare.done")))
+            throw new IllegalStateException("Graph has to be unprepared but wasn't!");
 
+        String chWeighting = args.get("prepare.chWeighting", "fastest");
         String vehicleStr = args.get("graph.flagEncoders", "car");
         FlagEncoder encoder = hopper.getEncodingManager().getEncoder(vehicleStr);
-        Weighting weighting = hopper.getCHFactoryDecorator().getWeightings().get(0);
-
+        Weighting weighting = hopper.getWeightingForCH(new WeightingMap(chWeighting), encoder);
         StopWatch sw = new StopWatch().start();
         try
         {
             maxNode = g.getNodes();
             GHBitSet allowedEdges = printGraphDetails(g, vehicleStr);
-            boolean isCH = false;
-            printMiscUnitPerfTests(g, isCH, encoder, count * 100, allowedEdges);
+            printMiscUnitPerfTests(false, g, encoder, count * 100, allowedEdges);
             printLocationIndexQuery(g, hopper.getLocationIndex(), count);
 
-            printTimeOfRouteQuery(hopper, isCH, count / 20, "routing", vehicleStr, true);
+            // Route via dijkstrabi. Normal routing takes a lot of time => smaller query number than CH
+            // => values are not really comparable to routingCH as e.g. the mean distance etc is different            
+            hopper.setCHEnable(false);
+            hopper.putAlgorithmFactory(weighting, new RoutingAlgorithmFactorySimple());
+            printTimeOfRouteQuery(hopper, count / 20, "routing", vehicleStr, true);
 
             System.gc();
 
+            // route via CH. do preparation before                        
+            hopper.setCHEnable(true);
+            hopper.doPostProcessing(weighting);
             CHGraph lg = g.getGraph(CHGraph.class, weighting);
             fillAllowedEdges(lg.getAllEdges(), allowedEdges);
-            isCH = true;
-            printMiscUnitPerfTests(lg, isCH, encoder, count * 100, allowedEdges);
-            printTimeOfRouteQuery(hopper, isCH, count, "routingCH", vehicleStr, true);
-            printTimeOfRouteQuery(hopper, isCH, count, "routingCH_no_instr", vehicleStr, false);
+            printMiscUnitPerfTests(true, lg, encoder, count * 100, allowedEdges);
+            printTimeOfRouteQuery(hopper, count, "routingCH", vehicleStr, true);
+            printTimeOfRouteQuery(hopper, count, "routingCH_no_instr", vehicleStr, false);
             logger.info("store into " + propLocation);
         } catch (Exception ex)
         {
@@ -204,7 +223,7 @@ public class Measurement
         print("location2id", miniPerf);
     }
 
-    private void printMiscUnitPerfTests( final Graph graph, boolean isCH, final FlagEncoder encoder,
+    private void printMiscUnitPerfTests( boolean isCH, final Graph graph, final FlagEncoder encoder,
                                          int count, final GHBitSet allowedEdges )
     {
         final Random rand = new Random(seed);
@@ -286,7 +305,7 @@ public class Measurement
         print("unit_tests" + description + ".get_edge_state", miniPerf);
     }
 
-    private void printTimeOfRouteQuery( final GraphHopper hopper, final boolean ch, int count, String prefix,
+    private void printTimeOfRouteQuery( final GraphHopper hopper, int count, String prefix,
                                         final String vehicle, final boolean withInstructions )
     {
         final Graph g = hopper.getGraphHopperStorage();
@@ -304,7 +323,7 @@ public class Measurement
 //        final AtomicLong tmpDist = new AtomicLong(0);
         final Random rand = new Random(seed);
         final NodeAccess na = g.getNodeAccess();
-
+        
         // if using none-bidirectional algorithm make sure you exclude CH routing
         final String algo = AlgorithmOptions.DIJKSTRA_BI;
         MiniPerfTest miniPerf = new MiniPerfTest()
@@ -322,9 +341,7 @@ public class Measurement
                         setWeighting("fastest").
                         setVehicle(vehicle).
                         setAlgorithm(algo);
-                if (!ch)
-                    req.getHints().put("routing.flexibleMode.force", true);
-
+                
                 // req.getHints().put(algo + ".approximation", "BeelineSimplification");
                 // req.getHints().put(algo + ".epsilon", 2);
                 req.getHints().put("instructions", withInstructions);
diff --git a/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java b/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java
index 693507684..48f0e7d53 100644
--- a/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java
+++ b/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java
@@ -40,10 +40,10 @@ import org.slf4j.LoggerFactory;
 
 /**
  * A rough graphical user interface for visualizing the OSM graph. Mainly for debugging algorithms
- * and spatial datastructures. See e.g. this blog post:
- * https://graphhopper.com/blog/2016/01/19/alternative-roads-to-rome/
+ * and spatial datastructures.
  * <p>
- * Use the web module for a better/faster/userfriendly/... alternative!
+ * Use the project at https://github.com/graphhopper/graphhopper-web for a
+ * better/faster/userfriendly/... alternative!
  * <p>
  * @author Peter Karich
  */
@@ -79,9 +79,8 @@ public class MiniGraphUI
         this.graph = hopper.getGraphHopperStorage();
         this.na = graph.getNodeAccess();
         encoder = hopper.getEncodingManager().getEncoder("car");
-        HintsMap map = new HintsMap("fastest");
-        weighting = hopper.createWeighting(map, encoder);
-        algoFactory = hopper.getAlgorithmFactory(map);
+        weighting = hopper.createWeighting(new WeightingMap("fastest"), encoder);
+        algoFactory = hopper.getAlgorithmFactory(weighting);
         algoOpts = new AlgorithmOptions(AlgorithmOptions.DIJKSTRA_BI, encoder, weighting);
 
         logger.info("locations:" + graph.getNodes() + ", debug:" + debug + ", algoOpts:" + algoOpts);
diff --git a/web/src/main/java/com/graphhopper/http/GraphHopperServlet.java b/web/src/main/java/com/graphhopper/http/GraphHopperServlet.java
index 9cc21372b..abaa64080 100644
--- a/web/src/main/java/com/graphhopper/http/GraphHopperServlet.java
+++ b/web/src/main/java/com/graphhopper/http/GraphHopperServlet.java
@@ -22,7 +22,7 @@ import com.graphhopper.GHRequest;
 import com.graphhopper.GHResponse;
 import com.graphhopper.GraphHopper;
 import com.graphhopper.routing.util.FlagEncoder;
-import com.graphhopper.routing.util.HintsMap;
+import com.graphhopper.routing.util.WeightingMap;
 import com.graphhopper.util.StopWatch;
 import com.graphhopper.util.shapes.GHPoint;
 import org.json.JSONObject;
@@ -273,7 +273,7 @@ public class GraphHopperServlet extends GHBaseServlet
 
     protected void initHints( GHRequest request, Map<String, String[]> parameterMap )
     {
-        HintsMap m = request.getHints();
+        WeightingMap m = request.getHints();
         for (Entry<String, String[]> e : parameterMap.entrySet())
         {
             if (e.getValue().length == 1)


Test patch:
diff --git a/core/src/test/java/com/graphhopper/GraphHopperAPITest.java b/core/src/test/java/com/graphhopper/GraphHopperAPITest.java
index f9d5c56e3..f8c9fa387 100644
--- a/core/src/test/java/com/graphhopper/GraphHopperAPITest.java
+++ b/core/src/test/java/com/graphhopper/GraphHopperAPITest.java
@@ -50,7 +50,8 @@ public class GraphHopperAPITest
 
         GraphHopper instance = new GraphHopper().
                 setStoreOnFlush(false).
-                setEncodingManager(encodingManager).setCHEnabled(false).
+                setEncodingManager(encodingManager).
+                setCHEnable(false).
                 loadGraph(graph);
         GHResponse rsp = instance.route(new GHRequest(42, 10.4, 42, 10));
         assertFalse(rsp.hasErrors());
@@ -81,7 +82,8 @@ public class GraphHopperAPITest
 
         GraphHopper instance = new GraphHopper().
                 setStoreOnFlush(false).
-                setEncodingManager(encodingManager).setCHEnabled(false).
+                setEncodingManager(encodingManager).
+                setCHEnable(false).
                 loadGraph(graph);
         GHResponse rsp = instance.route(new GHRequest(42, 10, 42, 10.4));
         assertTrue(rsp.hasErrors());
@@ -102,7 +104,8 @@ public class GraphHopperAPITest
     {
         GraphHopper instance = new GraphHopper().
                 setStoreOnFlush(false).
-                setEncodingManager(encodingManager).setCHEnabled(false);
+                setEncodingManager(encodingManager).
+                setCHEnable(false);
         try
         {
             instance.route(new GHRequest(42, 10.4, 42, 10));
diff --git a/core/src/test/java/com/graphhopper/GraphHopperIT.java b/core/src/test/java/com/graphhopper/GraphHopperIT.java
index 9d2767238..76ca5d96a 100644
--- a/core/src/test/java/com/graphhopper/GraphHopperIT.java
+++ b/core/src/test/java/com/graphhopper/GraphHopperIT.java
@@ -19,6 +19,8 @@ package com.graphhopper;
 
 import com.graphhopper.reader.dem.SRTMProvider;
 import com.graphhopper.routing.AlgorithmOptions;
+import com.graphhopper.routing.RoutingAlgorithmFactory;
+import com.graphhopper.routing.RoutingAlgorithmFactorySimple;
 import com.graphhopper.routing.util.EncodingManager;
 import com.graphhopper.util.*;
 import com.graphhopper.util.shapes.GHPoint;
@@ -65,7 +67,8 @@ public class GraphHopperIT
 
         hopper = new GraphHopper().
                 setStoreOnFlush(true).
-                setOSMFile(osmFile).setCHEnabled(false).
+                setOSMFile(osmFile).
+                setCHEnable(false).
                 setGraphHopperLocation(graphFileFoot).
                 setEncodingManager(new EncodingManager(importVehicles)).
                 importOrLoad();
@@ -150,7 +153,8 @@ public class GraphHopperIT
     public void testAlternativeRoutesBikeAndCar()
     {
         GraphHopper tmpHopper = new GraphHopper().
-                setOSMFile("files/north-bayreuth.osm.gz").setCHEnabled(false).
+                setOSMFile("files/north-bayreuth.osm.gz").
+                setCHEnable(false).
                 setGraphHopperLocation(tmpGraphFile).
                 setEncodingManager(new EncodingManager("bike, car"));
         tmpHopper.importOrLoad();
@@ -317,7 +321,8 @@ public class GraphHopperIT
     {
         GraphHopper tmpHopper = new GraphHopper().
                 setStoreOnFlush(true).
-                setOSMFile(osmFile).setCHEnabled(false).
+                setOSMFile(osmFile).
+                setCHEnable(false).
                 setGraphHopperLocation(tmpGraphFile).
                 setEncodingManager(new EncodingManager(importVehicles));
 
@@ -376,7 +381,8 @@ public class GraphHopperIT
 
         GraphHopper tmpHopper = new GraphHopper().
                 setStoreOnFlush(true).
-                setOSMFile(tmpOsmFile).setCHEnabled(false).
+                setOSMFile(tmpOsmFile).
+                setCHEnable(false).
                 setGraphHopperLocation(tmpGraphFile).
                 setEncodingManager(new EncodingManager(tmpImportVehicles)).
                 importOrLoad();
@@ -428,7 +434,11 @@ public class GraphHopperIT
 
         assertEquals(tmpVehicle, tmpHopper.getDefaultVehicle().toString());
 
-        assertEquals(2, tmpHopper.getCHFactoryDecorator().getPreparations().size());
+        assertEquals(2, tmpHopper.getAlgorithmFactories().size());
+        for (RoutingAlgorithmFactory raf : tmpHopper.getAlgorithmFactories())
+        {
+            assertFalse(RoutingAlgorithmFactorySimple.class.isAssignableFrom(raf.getClass()));
+        }
 
         GHResponse rsp = tmpHopper.route(new GHRequest(43.745084, 7.430513, 43.745247, 7.430347)
                 .setVehicle(tmpVehicle).setWeighting(tmpWeightCalcStr));
@@ -527,61 +537,22 @@ public class GraphHopperIT
         GraphHopper tmpHopper = new GraphHopper().
                 setStoreOnFlush(true).
                 setOSMFile(tmpOsmFile).
+                setCHWeightings(Arrays.asList(weightCalcStr)).
                 setGraphHopperLocation(tmpGraphFile).
-                setEncodingManager(new EncodingManager(tmpImportVehicles));
-        tmpHopper.getCHFactoryDecorator().setWeightingsAsStrings(weightCalcStr);
-        tmpHopper.importOrLoad();
+                setEncodingManager(new EncodingManager(tmpImportVehicles)).
+                importOrLoad();
 
         // same query as in testMonacoWithInstructions
         GHResponse rsp = tmpHopper.route(new GHRequest(43.727687, 7.418737, 43.74958, 7.436566).
                 setVehicle(vehicle));
 
-        PathWrapper bestPath = rsp.getBest();
+        PathWrapper arsp = rsp.getBest();
         // identify the number of counts to compare with none-CH foot route which had nearly 700 counts
         long sum = rsp.getHints().getLong("visited_nodes.sum", 0);
         assertNotEquals(sum, 0);
         assertTrue("Too many nodes visited " + sum, sum < 120);
-        assertEquals(3437.6, bestPath.getDistance(), .1);
-        assertEquals(89, bestPath.getPoints().getSize());
-
+        assertEquals(3437.6, arsp.getDistance(), .1);
+        assertEquals(89, arsp.getPoints().getSize());
         tmpHopper.close();
     }
-
-    @Test
-    public void testFlexMode_631()
-    {
-        String tmpOsmFile = "files/monaco.osm.gz";
-
-        GraphHopper tmpHopper = new GraphHopper().
-                setStoreOnFlush(true).
-                setOSMFile(tmpOsmFile).
-                setGraphHopperLocation(tmpGraphFile).
-                setEncodingManager(new EncodingManager("car"));
-
-        tmpHopper.getCHFactoryDecorator().
-                setWeightingsAsStrings(Arrays.asList("fastest")).
-                setForcingFlexibleModeAllowed(true);
-
-        tmpHopper.importOrLoad();
-
-        GHRequest req = new GHRequest(43.727687, 7.418737, 43.74958, 7.436566).
-                setVehicle("car");
-
-        GHResponse rsp = tmpHopper.route(req);
-        long sum = rsp.getHints().getLong("visited_nodes.sum", 0);
-        assertTrue("Too many visited nodes for ch mode " + sum, sum < 60);
-        PathWrapper bestPath = rsp.getBest();
-        assertEquals(3587, bestPath.getDistance(), 1);
-        assertEquals(92, bestPath.getPoints().getSize());
-
-        // now request flex mode
-        req.getHints().put("routing.flexibleMode.force", true);
-        rsp = tmpHopper.route(req);
-        sum = rsp.getHints().getLong("visited_nodes.sum", 0);
-        assertTrue("Too few visited nodes for flex mode " + sum, sum > 60);
-
-        bestPath = rsp.getBest();
-        assertEquals(3587, bestPath.getDistance(), 1);
-        assertEquals(92, bestPath.getPoints().getSize());
-    }
 }
diff --git a/core/src/test/java/com/graphhopper/GraphHopperTest.java b/core/src/test/java/com/graphhopper/GraphHopperTest.java
index e588032d8..ee56f8058 100644
--- a/core/src/test/java/com/graphhopper/GraphHopperTest.java
+++ b/core/src/test/java/com/graphhopper/GraphHopperTest.java
@@ -19,10 +19,10 @@ package com.graphhopper;
 
 import com.graphhopper.reader.DataReader;
 import com.graphhopper.routing.*;
-import com.graphhopper.routing.ch.CHAlgoFactoryDecorator;
 import com.graphhopper.routing.ch.PrepareContractionHierarchies;
 import com.graphhopper.routing.util.*;
 import com.graphhopper.storage.*;
+import com.graphhopper.storage.index.QueryResult;
 import com.graphhopper.util.CmdArgs;
 import com.graphhopper.util.Helper;
 import com.graphhopper.util.Instruction;
@@ -112,20 +112,19 @@ public class GraphHopperTest
     @Test
     public void testLoadOSMNoCH()
     {
-        GraphHopper gh = new GraphHopper().setStoreOnFlush(true).setCHEnabled(false).
+        GraphHopper gh = new GraphHopper().setStoreOnFlush(true).
+                setCHEnable(false).
                 setEncodingManager(new EncodingManager("CAR")).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm);
         gh.importOrLoad();
-
-        assertFalse(gh.getAlgorithmFactory(new HintsMap("fastest")) instanceof PrepareContractionHierarchies);
-
         GHResponse rsp = gh.route(new GHRequest(51.2492152, 9.4317166, 51.2, 9.4));
         assertFalse(rsp.hasErrors());
         assertEquals(3, rsp.getBest().getPoints().getSize());
 
         gh.close();
-        gh = new GraphHopper().setStoreOnFlush(true).setCHEnabled(false).
+        gh = new GraphHopper().setStoreOnFlush(true).
+                setCHEnable(false).
                 setEncodingManager(new EncodingManager("CAR"));
         assertTrue(gh.load(ghLoc));
         rsp = gh.route(new GHRequest(51.2492152, 9.4317166, 51.2, 9.4));
@@ -133,14 +132,6 @@ public class GraphHopperTest
         assertEquals(3, rsp.getBest().getPoints().getSize());
 
         gh.close();
-
-        gh = new GraphHopper().
-                setGraphHopperLocation(ghLoc).
-                setOSMFile(testOsm).
-                init(new CmdArgs().put("graph.flagEncoders", "CAR").put("prepare.chWeightings", "no"));
-
-        assertFalse(gh.getAlgorithmFactory(new HintsMap("fastest")) instanceof PrepareContractionHierarchies);
-        gh.close();
     }
 
     @Test
@@ -157,7 +148,8 @@ public class GraphHopperTest
         assertEquals(3, rsp.getBest().getPoints().getSize());
         gh.close();
 
-        gh = new GraphHopper().setStoreOnFlush(true).setCHEnabled(false).
+        gh = new GraphHopper().setStoreOnFlush(true).
+                setCHEnable(false).
                 setEncodingManager(new EncodingManager("CAR"));
         try
         {
@@ -171,7 +163,8 @@ public class GraphHopperTest
         Helper.removeDir(new File(ghLoc));
 
         // without CH should not be loadable with CH enabled
-        gh = new GraphHopper().setStoreOnFlush(true).setCHEnabled(false).
+        gh = new GraphHopper().setStoreOnFlush(true).
+                setCHEnable(false).
                 setEncodingManager(new EncodingManager("CAR")).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm);
@@ -290,9 +283,9 @@ public class GraphHopperTest
         instance = new GraphHopper().
                 setStoreOnFlush(false).
                 setEncodingManager(new EncodingManager("CAR")).
+                setCHWeightings(Arrays.asList("shortest")).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm);
-        instance.getCHFactoryDecorator().setWeightingsAsStrings("shortest");
         instance.importOrLoad();
         GHResponse rsp = instance.route(new GHRequest(51.2492152, 9.4317166, 51.2, 9.4).
                 setAlgorithm(AlgorithmOptions.DIJKSTRA_BI));
@@ -306,7 +299,8 @@ public class GraphHopperTest
     {
         instance = new GraphHopper().setStoreOnFlush(false).
                 setSortGraph(true).
-                setEncodingManager(new EncodingManager("CAR")).setCHEnabled(false).
+                setEncodingManager(new EncodingManager("CAR")).
+                setCHEnable(false).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm);
         instance.importOrLoad();
@@ -334,7 +328,8 @@ public class GraphHopperTest
     {
         // now all ways are imported
         instance = new GraphHopper().setStoreOnFlush(false).
-                setEncodingManager(new EncodingManager("CAR,FOOT")).setCHEnabled(false).
+                setEncodingManager(new EncodingManager("CAR,FOOT")).
+                setCHEnable(false).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm3);
         instance.importOrLoad();
@@ -383,7 +378,7 @@ public class GraphHopperTest
                 put("osmreader.osm", testOsm3).
                 put("osmreader.dataaccess", "RAM").
                 put("graph.flagEncoders", "FOOT,CAR").
-                put("prepare.chWeightings", "no")).
+                put("prepare.chWeighting", "no")).
                 setGraphHopperLocation(ghLoc);
         instance.importOrLoad();
         assertEquals(5, instance.getGraphHopperStorage().getNodes());
@@ -397,7 +392,7 @@ public class GraphHopperTest
                     put("osmreader.osm", testOsm3).
                     put("osmreader.dataaccess", "RAM").
                     put("graph.flagEncoders", "FOOT").
-                    put("prepare.chWeightings", "no")).
+                    put("prepare.chWeighting", "no")).
                     setOSMFile(testOsm3);
             tmpGH.load(ghLoc);
             assertTrue(false);
@@ -413,7 +408,7 @@ public class GraphHopperTest
                 put("osmreader.dataaccess", "RAM").
                 put("graph.flagEncoders", "FOOT,CAR").
                 put("graph.bytesForFlags", 8).
-                put("prepare.chWeightings", "no")).
+                put("prepare.chWeighting", "no")).
                 setOSMFile(testOsm3);
         try
         {
@@ -430,7 +425,7 @@ public class GraphHopperTest
             GraphHopper tmpGH = new GraphHopper().init(new CmdArgs().
                     put("osmreader.osm", testOsm3).
                     put("osmreader.dataaccess", "RAM").
-                    put("prepare.chWeightings", "no").
+                    put("prepare.chWeighting", "no").
                     put("graph.flagEncoders", "CAR,FOOT")).
                     setOSMFile(testOsm3);
             tmpGH.load(ghLoc);
@@ -566,6 +561,43 @@ public class GraphHopperTest
         assertEquals(Helper.createPointList(11.1, 50, 10, 51, 11.2, 52), rsp.getPoints());
     }
 
+    @Test
+    public void testPrepareOnly()
+    {
+        instance = new GraphHopper().setStoreOnFlush(true).
+                setCHWeightings(Arrays.asList("shortest")).
+                setEncodingManager(new EncodingManager("FOOT")).
+                setDoPrepare(false).
+                setGraphHopperLocation(ghLoc).
+                setOSMFile(testOsm3);
+        instance.importOrLoad();
+        instance.close();
+
+        instance = new GraphHopper().setStoreOnFlush(true).
+                setCHWeightings(Arrays.asList("shortest")).
+                setGraphHopperLocation(ghLoc).
+                setOSMFile(testOsm3);
+
+        // wrong encoding manager
+        instance.setEncodingManager(new EncodingManager("CAR"));
+        try
+        {
+            instance.load(ghLoc);
+            assertTrue(false);
+        } catch (IllegalStateException ex)
+        {
+            assertTrue(ex.getMessage(), ex.getMessage().startsWith("Encoding does not match:"));
+        }
+
+        // use the encoding manager from the graph
+        instance = new GraphHopper().setStoreOnFlush(true).
+                setEncodingManager(new EncodingManager("FOOT")).
+                setCHWeightings(Arrays.asList("shortest")).
+                setGraphHopperLocation(ghLoc).
+                setOSMFile(testOsm3);
+        instance.load(ghLoc);
+    }
+
     @Test
     public void testVia()
     {
@@ -609,6 +641,7 @@ public class GraphHopperTest
         // End at middle of edge 2-3
         GHPoint end = new GHPoint(0.002, 0.0005);
 
+        // Test enforce south start direction; expected nodes (9)-5-8-3-(10)
         GHRequest req = new GHRequest().addPoint(start, 180.).addPoint(end);
         GHResponse response = new GHResponse();
         List<Path> paths = instance.calcPaths(req, response);
@@ -622,7 +655,7 @@ public class GraphHopperTest
     @Test
     public void testGetPathsDirectionEnforcement2()
     {
-        // Test enforce south start direction and east end direction
+        // Test enforce start & end direction
         instance = createSquareGraphInstance(false);
 
         // Start in middle of edge 4-5 
@@ -630,6 +663,7 @@ public class GraphHopperTest
         // End at middle of edge 2-3
         GHPoint end = new GHPoint(0.002, 0.0005);
 
+        // Test enforce south start direction and east end direction ; expected nodes (9)-5-8-1-2-(10)
         GHRequest req = new GHRequest().addPoint(start, 180.).addPoint(end, 90.);
         GHResponse response = new GHResponse();
         List<Path> paths = instance.calcPaths(req, response);
@@ -792,9 +826,10 @@ public class GraphHopperTest
         g.edge(7, 8, 110, true);
 
         GraphHopper tmp = new GraphHopper().
-                setCHEnabled(withCH).
+                putAlgorithmFactory(weighting, null).
+                setCHEnable(withCH).
+                setCHWeightings(Arrays.asList("shortest")).
                 setEncodingManager(encodingManager);
-        tmp.getCHFactoryDecorator().setWeightingsAsStrings("fastest");
         tmp.setGraphHopperStorage(g);
         tmp.postProcessing();
 
@@ -806,53 +841,28 @@ public class GraphHopperTest
     {
         CarFlagEncoder carEncoder = new CarFlagEncoder();
         EncodingManager em = new EncodingManager(carEncoder);
-        // Weighting weighting = new FastestWeighting(carEncoder);
-        instance = new GraphHopper().setStoreOnFlush(false).setCHEnabled(false).
+        Weighting weighting = new FastestWeighting(carEncoder);
+        instance = new GraphHopper().setStoreOnFlush(false).
+                setCHEnable(false).
                 setEncodingManager(em).
                 setGraphHopperLocation(ghLoc).
                 setOSMFile(testOsm);
-        final RoutingAlgorithmFactory af = new RoutingAlgorithmFactorySimple();
-        instance.addAlgorithmFactoryDecorator(new RoutingAlgorithmFactoryDecorator()
-        {
-            @Override
-            public RoutingAlgorithmFactory getDecoratedAlgorithmFactory( RoutingAlgorithmFactory algoFactory, HintsMap map )
-            {
-                return af;
-            }
-
-            @Override
-            public boolean isEnabled()
-            {
-                return true;
-            }
-        });
+        RoutingAlgorithmFactory af = new RoutingAlgorithmFactorySimple();
+        instance.putAlgorithmFactory(weighting, af);
         instance.importOrLoad();
 
-        assertTrue(af == instance.getAlgorithmFactory(null));
+        assertTrue(af == instance.getAlgorithmFactory(weighting));
 
         // test that hints are passed to algorithm opts
         final AtomicInteger cnt = new AtomicInteger(0);
-        instance.addAlgorithmFactoryDecorator(new RoutingAlgorithmFactoryDecorator()
+        instance.putAlgorithmFactory(weighting, new RoutingAlgorithmFactorySimple()
         {
             @Override
-            public RoutingAlgorithmFactory getDecoratedAlgorithmFactory( RoutingAlgorithmFactory algoFactory, HintsMap map )
-            {
-                return new RoutingAlgorithmFactorySimple()
-                {
-                    @Override
-                    public RoutingAlgorithm createAlgo( Graph g, AlgorithmOptions opts )
-                    {
-                        cnt.addAndGet(1);
-                        assertFalse(opts.getHints().getBool("test", true));
-                        return super.createAlgo(g, opts);
-                    }
-                };
-            }
-
-            @Override
-            public boolean isEnabled()
+            public RoutingAlgorithm createAlgo( Graph g, AlgorithmOptions opts )
             {
-                return true;
+                cnt.addAndGet(1);
+                assertFalse(opts.getHints().getBool("test", true));
+                return super.createAlgo(g, opts);
             }
         });
         GHRequest req = new GHRequest(51.2492152, 9.4317166, 51.2, 9.4);
@@ -879,8 +889,8 @@ public class GraphHopperTest
 
             tmpGH.importOrLoad();
 
-            assertEquals(5, tmpGH.getCHFactoryDecorator().getPreparations().size());
-            for (RoutingAlgorithmFactory raf : tmpGH.getCHFactoryDecorator().getPreparations())
+            assertEquals(5, tmpGH.getAlgorithmFactories().size());
+            for (RoutingAlgorithmFactory raf : tmpGH.getAlgorithmFactories())
             {
                 PrepareContractionHierarchies pch = (PrepareContractionHierarchies) raf;
                 assertTrue("Preparation wasn't run! [" + threadCount + "]", pch.isPrepared());
@@ -923,37 +933,17 @@ public class GraphHopperTest
     @Test
     public void testGetWeightingForCH()
     {
+        GraphHopper hopper = new GraphHopper();
         TestEncoder truck = new TestEncoder("truck");
-        TestEncoder simpleTruck = new TestEncoder("simple_truck");
+        TestEncoder sTruck = new TestEncoder("simple_truck");
 
         // use simple truck first
-        EncodingManager em = new EncodingManager(simpleTruck, truck);
-        CHAlgoFactoryDecorator decorator = new CHAlgoFactoryDecorator();
-        Weighting fwSimpleT = new FastestWeighting(simpleTruck);
-        Weighting fwT = new FastestWeighting(truck);
-        RAMDirectory ramDir = new RAMDirectory();
-        GraphHopperStorage storage = new GraphHopperStorage(Arrays.asList(fwSimpleT, fwT), ramDir, em, false, new GraphExtension.NoOpExtension());
-        decorator.addWeighting(fwSimpleT);
-        decorator.addWeighting(fwT);
-        decorator.addPreparation(new PrepareContractionHierarchies(ramDir, storage, storage.getGraph(CHGraph.class, fwSimpleT), simpleTruck, fwSimpleT, TraversalMode.NODE_BASED));
-        decorator.addPreparation(new PrepareContractionHierarchies(ramDir, storage, storage.getGraph(CHGraph.class, fwT), truck, fwT, TraversalMode.NODE_BASED));
-
-        HintsMap wMap = new HintsMap("fastest");
-        wMap.put("vehicle", "truck");
-        assertEquals("fastest|truck", ((PrepareContractionHierarchies) decorator.getDecoratedAlgorithmFactory(null, wMap)).getWeighting().toString());
-        wMap.put("vehicle", "simple_truck");
-        assertEquals("fastest|simple_truck", ((PrepareContractionHierarchies) decorator.getDecoratedAlgorithmFactory(null, wMap)).getWeighting().toString());
-
-        // make sure weighting cannot be mixed
-        decorator.addWeighting(fwT);
-        decorator.addWeighting(fwSimpleT);
-        try
-        {
-            decorator.addPreparation(new PrepareContractionHierarchies(ramDir, storage, storage.getGraph(CHGraph.class, fwSimpleT), simpleTruck, fwSimpleT, TraversalMode.NODE_BASED));
-            assertTrue(false);
-        } catch (Exception ex)
-        {
-        }
+        new EncodingManager(sTruck, truck);
+        hopper.putAlgorithmFactory(new FastestWeighting(sTruck), new RoutingAlgorithmFactorySimple());
+        hopper.putAlgorithmFactory(new FastestWeighting(truck), new RoutingAlgorithmFactorySimple());
+
+        assertEquals("fastest|truck", hopper.getWeightingForCH(new WeightingMap("fastest"), truck).toString());
+        assertEquals("fastest|simple_truck", hopper.getWeightingForCH(new WeightingMap("fastest"), sTruck).toString());
     }
 
     @Test
@@ -961,11 +951,10 @@ public class GraphHopperTest
     {
         EncodingManager em = new EncodingManager(Arrays.asList(new CarFlagEncoder()), 8);
 
-        GraphHopper tmpGH = new GraphHopper().
-                setStoreOnFlush(false).
-                setEncodingManager(em);
-        tmpGH.getCHFactoryDecorator().setWeightingsAsStrings("fastest", "shortest");
+        GraphHopper tmpGH = new GraphHopper().setStoreOnFlush(false).
+                setEncodingManager(em).
+                setCHWeightings("fastest", "shortest");
 
-        assertEquals(2, tmpGH.getCHFactoryDecorator().getWeightingsAsStrings().size());
+        assertEquals(2, tmpGH.getCHWeightings().size());
     }
 }
diff --git a/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java b/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java
index d905e1fff..8810293c9 100644
--- a/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java
+++ b/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java
@@ -36,8 +36,11 @@ import org.junit.Before;
 import org.junit.Test;
 
 import com.graphhopper.GraphHopper;
+import com.graphhopper.GHRequest;
+import com.graphhopper.GHResponse;
 import com.graphhopper.reader.dem.ElevationProvider;
 import com.graphhopper.reader.dem.SRTMProvider;
+import com.graphhopper.routing.DijkstraBidirectionRef;
 import com.graphhopper.routing.util.*;
 import com.graphhopper.storage.*;
 import com.graphhopper.storage.index.QueryResult;
@@ -64,6 +67,7 @@ public class OSMReaderTest
     // test-osm6.pbf was created by running "osmconvert test-osm6.xml --timestamp=2014-01-02T00:10:14Z -o=test-osm6.pbf"
     // The osmconvert tool can be found here: http://wiki.openstreetmap.org/wiki/Osmconvert
     private final String file6 = "test-osm6.pbf";
+    private final String file7 = "test-osm7.xml";
     private final String fileNegIds = "test-osm-negative-ids.xml";
     private final String fileBarriers = "test-barriers.xml";
     private final String fileTurnRestrictions = "test-restrictions.xml";
@@ -105,7 +109,7 @@ public class OSMReaderTest
             setOSMFile(osmFile);
             setGraphHopperLocation(dir);
             setEncodingManager(new EncodingManager("CAR,FOOT"));
-            setCHEnabled(false);
+            setCHEnable(false);
 
             if (turnCosts)
             {
@@ -854,4 +858,20 @@ public class OSMReaderTest
         assertEquals(-179.6, qr.getSnappedPoint().lon, 0.1);
         assertEquals(56, qr.getClosestEdge().getDistance() / 1000, 1);
     }
+
+    public void testRoutingRequestFails_issue665()
+    {
+        GraphHopper hopper = new GraphHopper();
+        hopper.setOSMFile("src/test/resources/com/graphhopper/reader/" + file7);
+        hopper.setEncodingManager(new EncodingManager("car,motorcycle"));
+        hopper.setCHEnable(false);
+        hopper.setGraphHopperLocation(dir);
+        hopper.importOrLoad();
+        GHRequest req = new GHRequest(48.97725592769741, 8.256896138191223, 48.978875552977684, 8.25486302375793).
+                setWeighting("curvature").
+                setVehicle("motorcycle");
+
+        GHResponse ghRsp = hopper.route(req);
+        assertFalse(ghRsp.getErrors().toString(), ghRsp.hasErrors());
+    }
 }
diff --git a/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java b/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java
index 218e2447d..3a7dad7aa 100644
--- a/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java
+++ b/core/src/test/java/com/graphhopper/routing/AbstractRoutingAlgorithmTester.java
@@ -759,7 +759,7 @@ public abstract class AbstractRoutingAlgorithmTester
             }
 
             @Override
-            public boolean matches( HintsMap map )
+            public boolean matches( String weightingAsStr, FlagEncoder encoder )
             {
                 throw new UnsupportedOperationException("Not supported");
             }
diff --git a/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java b/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java
index fd57040d2..46cc288a1 100644
--- a/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java
+++ b/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java
@@ -154,14 +154,15 @@ public class RoutingAlgorithmIT
         GraphHopper hopper = new GraphHopper().
                 // avoid that path.getDistance is too different to path.getPoint.calcDistance
                 setWayPointMaxDistance(0).
-                setOSMFile(osmFile).setCHEnabled(false).
+                setOSMFile(osmFile).
+                setCHEnable(false).
                 setGraphHopperLocation(graphFile).
                 setEncodingManager(new EncodingManager(importVehicles));
 
         hopper.importOrLoad();
 
         FlagEncoder encoder = hopper.getEncodingManager().getEncoder(vehicle);
-        Weighting weighting = hopper.createWeighting(new HintsMap("shortest"), encoder);
+        Weighting weighting = hopper.createWeighting(new WeightingMap("shortest"), encoder);
 
         List<AlgoHelperEntry> prepares = createAlgos(hopper.getGraphHopperStorage(), hopper.getLocationIndex(),
                 encoder, true, TraversalMode.NODE_BASED, weighting, hopper.getEncodingManager());
@@ -567,7 +568,8 @@ public class RoutingAlgorithmIT
                     setStoreOnFlush(true).
                     // avoid that path.getDistance is too different to path.getPoint.calcDistance
                     setWayPointMaxDistance(0).
-                    setOSMFile(osmFile).setCHEnabled(false).
+                    setOSMFile(osmFile).
+                    setCHEnable(false).
                     setGraphHopperLocation(graphFile).
                     setEncodingManager(new EncodingManager(importVehicles));
             if (is3D)
@@ -578,7 +580,7 @@ public class RoutingAlgorithmIT
             TraversalMode tMode = importVehicles.toLowerCase().contains("turncosts=true")
                     ? TraversalMode.EDGE_BASED_1DIR : TraversalMode.NODE_BASED;
             FlagEncoder encoder = hopper.getEncodingManager().getEncoder(vehicle);
-            Weighting weighting = hopper.createWeighting(new HintsMap(weightStr), encoder);
+            Weighting weighting = hopper.createWeighting(new WeightingMap(weightStr), encoder);
 
             Collection<AlgoHelperEntry> prepares = createAlgos(hopper.getGraphHopperStorage(),
                     hopper.getLocationIndex(), encoder, testAlsoCH, tMode, weighting, hopper.getEncodingManager());
@@ -659,7 +661,8 @@ public class RoutingAlgorithmIT
         final EncodingManager encodingManager = new EncodingManager("CAR");
         GraphHopper hopper = new GraphHopper().
                 setStoreOnFlush(true).
-                setEncodingManager(encodingManager).setCHEnabled(false).
+                setEncodingManager(encodingManager).
+                setCHEnable(false).
                 setWayPointMaxDistance(0).
                 setOSMFile("files/monaco.osm.gz").
                 setGraphHopperLocation(graphFile).
diff --git a/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java b/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java
index a00ee3377..23fe7fcb8 100644
--- a/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java
+++ b/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java
@@ -157,20 +157,6 @@ public abstract class AbstractBikeFlagEncoderTester
         way.setTag("bicycle", "yes");
         assertTrue(encoder.acceptWay(way) > 0);
 
-        way.clearTags();
-        way.setTag("highway", "secondary");
-        way.setTag("access", "no");
-        assertFalse(encoder.acceptWay(way) > 0);
-        way.setTag("bicycle", "dismount");
-        assertTrue(encoder.acceptWay(way) > 0);
-
-        way.clearTags();
-        way.setTag("highway", "secondary");
-        way.setTag("vehicle", "no");
-        assertFalse(encoder.acceptWay(way) > 0);
-        way.setTag("bicycle", "dismount");
-        assertTrue(encoder.acceptWay(way) > 0);
-
         way.clearTags();
         way.setTag("route", "ferry");
         assertTrue(encoder.acceptWay(way) > 0);
@@ -366,13 +352,6 @@ public abstract class AbstractBikeFlagEncoderTester
         way.setTag("railway", "platform");
         wayType = getWayTypeFromFlags(way);
         assertEquals("get off the bike, unpaved", wayType);
-
-        way.clearTags();
-        way.setTag("highway", "secondary");
-        way.setTag("bicycle", "dismount");
-        wayType = getWayTypeFromFlags(way);
-        assertEquals("get off the bike", wayType);
-
     }
 
     @Test
diff --git a/core/src/test/java/com/graphhopper/routing/util/Bike2WeightFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/Bike2WeightFlagEncoderTest.java
index 922ce6164..26c091c11 100644
--- a/core/src/test/java/com/graphhopper/routing/util/Bike2WeightFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/Bike2WeightFlagEncoderTest.java
@@ -20,9 +20,7 @@ package com.graphhopper.routing.util;
 
 import com.graphhopper.reader.OSMWay;
 import com.graphhopper.storage.*;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.GHUtility;
-import com.graphhopper.util.Helper;
+import com.graphhopper.util.*;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
@@ -94,4 +92,43 @@ public class Bike2WeightFlagEncoderTest extends BikeFlagEncoderTest
         assertFalse(encoder.isForward(flags));
         assertTrue(encoder.isBackward(flags));
     }
+
+    @Test
+    public void testRoutingFailsWithInvalidGraph_issue665()
+    {
+        GraphHopperStorage graph = new GraphHopperStorage(
+                new RAMDirectory(), em, true, new GraphExtension.NoOpExtension());
+        graph.create(100);
+
+        OSMWay way = new OSMWay(0);
+        way.setTag("route", "ferry");
+
+        long includeWay = em.acceptWay(way);
+        long relationFlags = 0;
+        long wayFlags = em.handleWayTags(way, includeWay, relationFlags);
+        graph.edge(0, 1).setDistance(247).setFlags(wayFlags);
+
+        assertTrue(isGraphValid(graph, encoder));
+    }
+
+    private boolean isGraphValid( Graph graph, FlagEncoder encoder )
+    {
+        EdgeExplorer explorer = graph.createEdgeExplorer();
+
+        // iterator at node 0 considers the edge 0-1 to be undirected
+        EdgeIterator iter0 = explorer.setBaseNode(0);
+        iter0.next();
+        boolean iter0flag
+                = iter0.getBaseNode() == 0 && iter0.getAdjNode() == 1
+                && iter0.isForward(encoder) && iter0.isBackward(encoder);
+
+        // iterator at node 1 considers the edge 1-0 to be directed
+        EdgeIterator iter1 = explorer.setBaseNode(1);
+        iter1.next();
+        boolean iter1flag
+                = iter1.getBaseNode() == 1 && iter1.getAdjNode() == 0
+                && iter1.isForward(encoder) && iter1.isBackward(encoder);
+
+        return iter0flag && iter1flag;
+    }
 }
diff --git a/core/src/test/java/com/graphhopper/routing/util/BikeFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/BikeFlagEncoderTest.java
index b29464152..5068f94ac 100644
--- a/core/src/test/java/com/graphhopper/routing/util/BikeFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/BikeFlagEncoderTest.java
@@ -65,12 +65,6 @@ public class BikeFlagEncoderTest extends AbstractBikeFlagEncoderTester
         assertEquals(PUSHING_SECTION_SPEED, encoder.getSpeed(way));
         assertPriority(AVOID_IF_POSSIBLE.getValue(), way);
 
-        way.clearTags();
-        way.setTag("highway", "secondary");
-        way.setTag("bicycle", "dismount");
-        assertEquals(PUSHING_SECTION_SPEED, encoder.getSpeed(way));
-        assertPriority(REACH_DEST.getValue(), way);
-
         way.clearTags();
         way.setTag("highway", "footway");
         way.setTag("bicycle", "yes");
@@ -129,15 +123,6 @@ public class BikeFlagEncoderTest extends AbstractBikeFlagEncoderTester
         assertEquals(2, encoder.getSpeed(way));
         assertPriority(AVOID_IF_POSSIBLE.getValue(), way);
 
-        way.clearTags();
-        way.setTag("highway", "steps");
-        way.setTag("surface", "wood");
-        assertEquals(PUSHING_SECTION_SPEED/2, encoder.getSpeed(way));
-        assertPriority(AVOID_IF_POSSIBLE.getValue(), way);
-        way.setTag("maxspeed", "20");        
-        assertEquals(PUSHING_SECTION_SPEED/2, encoder.getSpeed(way));
-        assertPriority(AVOID_IF_POSSIBLE.getValue(), way);
-
         way.clearTags();
         way.setTag("highway", "track");
         way.setTag("surface", "paved");
diff --git a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
index ebea111d0..d05477b31 100644
--- a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
@@ -385,7 +385,7 @@ public class CarFlagEncoderTest
         // accept
         assertTrue(encoder.acceptWay(way) > 0);
         // calculate speed from estimated_distance and duration
-        assertEquals(60, encoder.getSpeed(encoder.handleFerryTags(way, 20, 30, 40)), 1e-1);
+        assertEquals(61, encoder.getFerrySpeed(way, 20, 30, 40), 1e-1);
 
         //Test for very short and slow 0.5km/h still realisitic ferry
         way = new OSMWay(1);
@@ -397,8 +397,9 @@ public class CarFlagEncoderTest
         // accept
         assertTrue(encoder.acceptWay(way) > 0);
         // We can't store 0.5km/h, but we expect the lowest possible speed (5km/h)
-        assertEquals(5, encoder.getSpeed(encoder.handleFerryTags(way, 20, 30, 40)), 1e-1);
-
+        assertEquals(2.5, encoder.getFerrySpeed(way, 20, 30, 40), 1e-1);
+        assertEquals(5, encoder.getSpeed(encoder.setSpeed(0, 2.5)), 1e-1);
+        
         //Test for an unrealisitic long duration
         way = new OSMWay(1);
         way.setTag("route", "ferry");
@@ -409,8 +410,7 @@ public class CarFlagEncoderTest
         // accept
         assertTrue(encoder.acceptWay(way) > 0);
         // We have ignored the unrealisitc long duration and take the unknown speed
-        assertEquals(20, encoder.getSpeed(encoder.handleFerryTags(way, 20, 30, 40)), 1e-1);
-
+        assertEquals(20, encoder.getFerrySpeed(way, 20, 30, 40), 1e-1);
     }
 
     @Test
diff --git a/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java
index c42ac6889..ecf9fff3a 100644
--- a/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java
@@ -126,15 +126,6 @@ public class FootFlagEncoderTest
         way.setTag("highway", "service");
         way.setTag("access", "no");
         assertFalse(footEncoder.acceptWay(way) > 0);
-        way.setTag("foot", "yes");
-        assertTrue(footEncoder.acceptWay(way) > 0);
-
-        way.clearTags();
-        way.setTag("highway", "service");
-        way.setTag("vehicle", "no");
-        assertFalse(footEncoder.acceptWay(way) > 0);
-        way.setTag("foot", "yes");
-        assertTrue(footEncoder.acceptWay(way) > 0);
 
         way.clearTags();
         way.setTag("highway", "tertiary");
diff --git a/core/src/test/resources/com/graphhopper/reader/test-osm7.xml b/core/src/test/resources/com/graphhopper/reader/test-osm7.xml
new file mode 100644
index 000000000..39be21111
--- /dev/null
+++ b/core/src/test/resources/com/graphhopper/reader/test-osm7.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<osm version="0.6" generator="CGImap 0.4.0 (21273 thorn-02.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
+ <bounds minlat="48.9772300" minlon="8.2547700" maxlat="48.9789600" maxlon="8.2570200"/>
+ <node id="15230524" visible="true" version="10" changeset="31551591" timestamp="2015-05-28T23:31:48Z" user="maction" uid="62423" lat="48.9788809" lon="8.2548809">
+  <tag k="amenity" v="ferry_terminal"/>
+  <tag k="cargo" v="passengers;vehicle"/>
+  <tag k="name" v="Rheinfähre Neuburg"/>
+  <tag k="TMC:cid_58:tabcd_1:Class" v="Point"/>
+  <tag k="TMC:cid_58:tabcd_1:LCLversion" v="9.00"/>
+  <tag k="TMC:cid_58:tabcd_1:LocationCode" v="53045"/>
+  <tag k="TMC:cid_58:tabcd_1:NextLocationCode" v="54998"/>
+ </node>
+ <node id="1422857309" visible="true" version="1" changeset="9207458" timestamp="2011-09-04T10:34:59Z" user="KK-O" uid="14228" lat="48.9788068" lon="8.2554001"/>
+  <node id="1422857311" visible="true" version="1" changeset="9207458" timestamp="2011-09-04T10:34:59Z" user="KK-O" uid="14228" lat="48.9781625" lon="8.2562316"/>
+ <node id="1422857313" visible="true" version="1" changeset="9207458" timestamp="2011-09-04T10:34:59Z" user="KK-O" uid="14228" lat="48.9776344" lon="8.2568485"/>
+  <node id="15237462" visible="true" version="8" changeset="27528220" timestamp="2014-12-17T12:00:56Z" user="guenz" uid="176514" lat="48.9772732" lon="8.2569129">
+  <tag k="amenity" v="ferry_terminal"/>
+  <tag k="cargo" v="passengers;vehicle"/>
+  <tag k="name" v="Rheinfähre Neuburg"/>
+  <tag k="TMC:cid_58:tabcd_1:Class" v="Point"/>
+  <tag k="TMC:cid_58:tabcd_1:LCLversion" v="9.00"/>
+  <tag k="TMC:cid_58:tabcd_1:LocationCode" v="53046"/>
+  <tag k="TMC:cid_58:tabcd_1:PrevLocationCode" v="54998"/>
+ </node>
+ <way id="3500103" visible="true" version="13" changeset="34403208" timestamp="2015-10-03T08:12:50Z" user="W0lle" uid="2111313">
+  <nd ref="15230524"/>
+  <nd ref="1422857309"/>
+  <nd ref="1422857311"/>
+  <nd ref="1422857313"/>
+  <nd ref="15237462"/>
+  <tag k="duration" v="00:04"/>
+  <tag k="fee" v="yes"/>
+  <tag k="motorcar" v="yes"/>
+  <tag k="motor_vehicle" v="yes"/>
+  <tag k="name" v="Rheinfähre Neuburg"/>
+  <tag k="note" v="Fährverbindung März - Nov"/>
+  <tag k="ref" v="F3"/>
+  <tag k="route" v="ferry"/>
+  <tag k="tmc" v="DE:53045+54998;DE:54998-53045"/>
+  <tag k="TMC:cid_58:tabcd_1:Class" v="Point"/>
+  <tag k="TMC:cid_58:tabcd_1:LCLversion" v="9.00"/>
+  <tag k="TMC:cid_58:tabcd_1:LocationCode" v="54998"/>
+  <tag k="TMC:cid_58:tabcd_1:NextLocationCode" v="53046"/>
+  <tag k="TMC:cid_58:tabcd_1:PrevLocationCode" v="53045"/>
+  <tag k="website" v="http://www.rheinfaehre-neuburg.de/Home.html"/>
+ </way>
+</osm>
diff --git a/web/src/test/java/com/graphhopper/http/GraphHopperServletWithEleIT.java b/web/src/test/java/com/graphhopper/http/GraphHopperServletWithEleIT.java
index 4012b3507..248b1cdee 100644
--- a/web/src/test/java/com/graphhopper/http/GraphHopperServletWithEleIT.java
+++ b/web/src/test/java/com/graphhopper/http/GraphHopperServletWithEleIT.java
@@ -49,7 +49,7 @@ public class GraphHopperServletWithEleIT extends BaseServletTester
         CmdArgs args = new CmdArgs().
                 put("graph.elevation.provider", "srtm").
                 put("graph.elevation.cachedir", "../core/files/").
-                put("prepare.chWeightings", "no").
+                put("prepare.chWeighting", "no").
                 put("config", "../config-example.properties").
                 put("osmreader.osm", "../core/files/monaco.osm.gz").
                 put("graph.location", dir);
diff --git a/web/src/test/java/com/graphhopper/http/NearestServletWithEleIT.java b/web/src/test/java/com/graphhopper/http/NearestServletWithEleIT.java
index 4db148920..cb8f5c269 100644
--- a/web/src/test/java/com/graphhopper/http/NearestServletWithEleIT.java
+++ b/web/src/test/java/com/graphhopper/http/NearestServletWithEleIT.java
@@ -52,7 +52,7 @@ public class NearestServletWithEleIT extends BaseServletTester
         CmdArgs args = new CmdArgs().
                 put("graph.elevation.provider", "srtm").
                 put("graph.elevation.cachedir", "../core/files/").
-                put("prepare.chWeightings", "no").
+                put("prepare.chWeighting", "no").
                 put("config", "../config-example.properties").
                 put("osmreader.osm", "../core/files/monaco.osm.gz").
                 put("graph.location", dir);