Skip to content

Commit

Permalink
Move ProfileResolver out of GraphHopper class, strictly require routi…
Browse files Browse the repository at this point in the history
…ng profiles (#1958)
  • Loading branch information
easbar committed Mar 23, 2020
1 parent 04d6a44 commit 6daf068
Show file tree
Hide file tree
Showing 47 changed files with 1,355 additions and 784 deletions.
12 changes: 12 additions & 0 deletions api/src/main/java/com/graphhopper/GHRequest.java
Expand Up @@ -34,6 +34,9 @@
*/
public class GHRequest {
private List<GHPoint> points;
// todo #1934: keep this here or put it into hints, and even more important: remove vehicle+weighting from
// hints?
private String profile = "";
private final HintsMap hints = new HintsMap();
// List of favored start (1st element) and arrival heading (all other).
// Headings are north based azimuth (clockwise) in (0, 360) or NaN for equal preference
Expand Down Expand Up @@ -223,6 +226,15 @@ public GHRequest setLocale(String localeStr) {
return setLocale(Helper.getLocale(localeStr));
}

public String getProfile() {
return profile;
}

public GHRequest setProfile(String profile) {
this.profile = profile;
return this;
}

public String getWeighting() {
return hints.getWeighting();
}
Expand Down
Expand Up @@ -285,7 +285,7 @@ public void testExportWithoutTrack() {
String res = gh.export(req);
assertTrue(res.contains("<gpx"));
assertTrue(res.contains("<rtept lat="));
assertTrue(!res.contains("<trk><name>GraphHopper Track</name><trkseg>"));
assertFalse(res.contains("<trk><name>GraphHopper Track</name><trkseg>"));
assertTrue(res.endsWith("</gpx>"));
}

Expand Down
3 changes: 2 additions & 1 deletion config-example.yml
Expand Up @@ -22,7 +22,8 @@ graphhopper:

##### Routing Profiles ####

# Routing can be done for the following list of profiles. The fields of each profile are as follows:
# Routing can be done for the following list of profiles. Note that it is required to specify all the profiles you
# would like to use here. The fields of each profile are as follows:
# - name (required): a unique string identifier for the profile
# - vehicle (required): refers to the `graph.flag_encoders` used for this profile
# - weighting (required): the weighting used for this profile, e.g. fastest,shortest or short_fastest
Expand Down
3 changes: 3 additions & 0 deletions core/files/changelog.txt
@@ -1,4 +1,7 @@
1.0
removed vehicle,weighting and edge_based from GraphHopper class, replaced with new profile parameter, #1958
all routing profiles have to be configured when setting up GraphHopper, #1958
there no longer is a default vehicle, not setting the vehicle now only works if there is exactly one profile that matches the other parameters. anyway you should use the new profile rather than the vehicle parameter.
removed IPFilter. Use a firewall instead.
PMap refactored. It is recommended to use putObject(String, Object) instead of put, #1956
removed UnsafeDataAccess as not maintained, see #1620
Expand Down
70 changes: 40 additions & 30 deletions core/src/main/java/com/graphhopper/GraphHopper.java
Expand Up @@ -24,7 +24,10 @@
import com.graphhopper.reader.DataReader;
import com.graphhopper.reader.dem.*;
import com.graphhopper.reader.osm.conditional.DateRangeParser;
import com.graphhopper.routing.*;
import com.graphhopper.routing.AlgorithmOptions;
import com.graphhopper.routing.Path;
import com.graphhopper.routing.RoutingAlgorithmFactory;
import com.graphhopper.routing.RoutingAlgorithmFactorySimple;
import com.graphhopper.routing.ch.CHPreparationHandler;
import com.graphhopper.routing.ch.CHRoutingAlgorithmFactory;
import com.graphhopper.routing.lm.LMPreparationHandler;
Expand Down Expand Up @@ -102,8 +105,6 @@ public class GraphHopper implements GraphHopperAPI {
private boolean smoothElevation = false;
// for routing
private final RoutingConfig routingConfig = new RoutingConfig();
private ProfileResolver profileResolver = new ProfileResolver();

// for index
private LocationIndex locationIndex;
private int preciseIndexResolution = 300;
Expand Down Expand Up @@ -140,13 +141,6 @@ protected GraphHopper loadGraph(GraphHopperStorage g) {
return this;
}

FlagEncoder getDefaultVehicle() {
if (encodingManager == null)
throw new IllegalStateException("No encoding manager specified or loaded");

return profileResolver.getDefaultVehicle(encodingManager);
}

public EncodingManager getEncodingManager() {
return encodingManager;
}
Expand Down Expand Up @@ -491,15 +485,6 @@ public GraphHopper setTagParserFactory(TagParserFactory factory) {
return this;
}

public ProfileResolver getProfileResolver() {
return this.profileResolver;
}

public GraphHopper setProfileResolver(ProfileResolver profileResolver) {
this.profileResolver = profileResolver;
return this;
}

/**
* Reads the configuration from a {@link GraphHopperConfig} object which can be manually filled, or more typically
* is read from `config.yml`.
Expand Down Expand Up @@ -824,6 +809,11 @@ public boolean load(String graphHopperFolder) {
}

private void checkProfilesConsistency() {
// todo: strictly speaking no profiles are needed, e.g. when we only use the location index, but this is rather
// the exception. we can move this check closer to the code that actually requires profiles after #1901
if (profilesByName.isEmpty()) {
throw new IllegalArgumentException("No routing profiles have been specified, you need to configure at least one");
}
for (ProfileConfig profile : profilesByName.values()) {
if (!encodingManager.hasEncoder(profile.getVehicle())) {
throw new IllegalArgumentException("Unknown vehicle '" + profile.getVehicle() + "' in profile: " + profile + ". Make sure all vehicles used in 'profiles' exist in 'graph.flag_encoders'");
Expand Down Expand Up @@ -864,13 +854,6 @@ private void checkProfilesConsistency() {
}
}

public ProfileConfig resolveProfile(HintsMap hints) {
if (encodingManager == null)
throw new IllegalStateException("No encoding manager specified or loaded");

return profileResolver.resolveProfile(encodingManager, chPreparationHandler.getCHProfiles(), lmPreparationHandler.getLMProfiles(), hints);
}

public RoutingAlgorithmFactory getAlgorithmFactory(String profile, boolean disableCH, boolean disableLM) {
if (chPreparationHandler.isEnabled() && disableCH && !chPreparationHandler.isDisablingAllowed()) {
throw new IllegalArgumentException("Disabling CH is not allowed on the server side");
Expand Down Expand Up @@ -1030,7 +1013,18 @@ public List<Path> calcPaths(GHRequest request, GHResponse ghRsp) {
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
HintsMap hints = request.getHints();
if (!request.getVehicle().isEmpty())
throw new IllegalArgumentException("GHRequest may no longer contain a vehicle, use the profile parameter instead, see #1958");
if (!request.getWeighting().isEmpty())
throw new IllegalArgumentException("GHRequest may no longer contain a weighting, use the profile parameter instead, see #1958");
if (request.getHints().has(Routing.TURN_COSTS))
throw new IllegalArgumentException("GHRequest may no longer contain the turn_costs=true/false parameter, use the profile parameter instead, see #1958");
if (request.getHints().has(Routing.EDGE_BASED))
throw new IllegalArgumentException("GHRequest may no longer contain the edge_based=true/false parameter, use the profile parameter instead, see #1958");

// todo later: do not allow things like short_fastest.distance_factor or u_turn_costs unless CH is disabled and only under certain conditions for LM

PMap hints = request.getHints();
boolean disableCH = hints.getBool(CH.DISABLE, false);
if (chPreparationHandler.isEnabled() && !chPreparationHandler.isDisablingAllowed() && disableCH)
throw new IllegalArgumentException("Disabling CH not allowed on the server-side");
Expand All @@ -1056,10 +1050,17 @@ public List<Path> calcPaths(GHRequest request, GHResponse ghRsp) {
// For example see #734
checkIfPointsAreInBounds(points);

ProfileConfig profile = resolveProfile(hints);
if (Helper.isEmpty(request.getProfile())) {
throw new IllegalArgumentException("You need to specify a profile to perform a routing request, see #1958");
}
ProfileConfig profile = profilesByName.get(request.getProfile());
if (profile == null) {
throw new IllegalArgumentException("The requested profile '" + request.getProfile() + "' does not exist");
}
if (!profile.isTurnCosts() && !request.getCurbsides().isEmpty())
throw new IllegalArgumentException("To make use of the " + CURBSIDE + " parameter you need to use a profile that supports turn costs");

// todo later: should we be able to control this using the edge_based parameter?
TraversalMode tMode = profile.isTurnCosts() ? TraversalMode.EDGE_BASED : TraversalMode.NODE_BASED;

RoutingAlgorithmFactory algorithmFactory = getAlgorithmFactory(profile.getName(), disableCH, disableLM);
Expand Down Expand Up @@ -1350,13 +1351,22 @@ public DefaultWeightingFactory(EncodingManager encodingManager, GraphHopperStora
this.ghStorage = ghStorage;
}

public Weighting createWeighting(ProfileConfig profile, PMap hints) {
public Weighting createWeighting(ProfileConfig profile, PMap requestHints) {
// Merge profile hints with request hints, the request hints take precedence.
// Note that so far we do not check if overwriting the profile hints actually works with the preparation
// for LM/CH. Later we should also limit the number of parameters that can be used to modify the profile.
// todo: since we are not dealing with block_area here yet we cannot really apply any merging rules
// for it, see discussion here: https://github.com/graphhopper/graphhopper/pull/1958#discussion_r395462901
PMap hints = new PMap();
hints.putAll(profile.getHints());
hints.putAll(requestHints);

FlagEncoder encoder = encodingManager.getEncoder(profile.getVehicle());
TurnCostProvider turnCostProvider;
if (profile.isTurnCosts() && !hints.getBool("__disable_turn_costs_for_lm_preparation", false)) {
if (!encoder.supportsTurnCosts())
throw new IllegalArgumentException("Encoder " + encoder + " does not support turn costs");
int uTurnCosts = profile.getHints().getInt(Routing.U_TURN_COSTS, INFINITE_U_TURN_COSTS);
int uTurnCosts = hints.getInt(Routing.U_TURN_COSTS, INFINITE_U_TURN_COSTS);
turnCostProvider = new DefaultTurnCostProvider(encoder, ghStorage.getTurnCostStorage(), uTurnCosts);
} else {
turnCostProvider = NO_TURN_COST_PROVIDER;
Expand Down

0 comments on commit 6daf068

Please sign in to comment.