18
18
19
19
package com .graphhopper .http ;
20
20
21
+ import com .bedatadriven .jackson .datatype .jts .JtsModule ;
21
22
import com .fasterxml .jackson .databind .ObjectMapper ;
22
23
import com .graphhopper .GraphHopper ;
23
24
import com .graphhopper .GraphHopperConfig ;
28
29
import com .graphhopper .routing .weighting .custom .CustomWeighting ;
29
30
import com .graphhopper .util .CustomModel ;
30
31
import com .graphhopper .util .Helper ;
32
+ import com .graphhopper .util .JsonFeature ;
33
+ import com .graphhopper .util .JsonFeatureCollection ;
31
34
import io .dropwizard .lifecycle .Managed ;
32
35
import org .slf4j .Logger ;
33
36
import org .slf4j .LoggerFactory ;
34
37
38
+ import java .io .BufferedReader ;
35
39
import java .io .File ;
40
+ import java .io .IOException ;
41
+ import java .io .UncheckedIOException ;
42
+ import java .nio .charset .StandardCharsets ;
43
+ import java .nio .file .DirectoryStream ;
44
+ import java .nio .file .Files ;
45
+ import java .nio .file .Path ;
36
46
import java .nio .file .Paths ;
37
47
import java .util .ArrayList ;
38
48
import java .util .List ;
@@ -50,13 +60,29 @@ public GraphHopperManaged(GraphHopperConfig configuration) {
50
60
}
51
61
52
62
String customModelFolder = configuration .getString ("custom_model_folder" , "" );
53
- List <Profile > newProfiles = resolveCustomModelFiles (customModelFolder , configuration .getProfiles ());
63
+ String customAreasDirectory = configuration .getString ("custom_areas.directory" , "" );
64
+ JsonFeatureCollection globalAreas = new JsonFeatureCollection ();
65
+ if (!customAreasDirectory .isEmpty ()) {
66
+ ObjectMapper mapper = new ObjectMapper ().registerModule (new JtsModule ());
67
+ try (DirectoryStream <Path > stream = Files .newDirectoryStream (Paths .get (customAreasDirectory ), "*.{geojson,json}" )) {
68
+ for (Path customAreaFile : stream ) {
69
+ try (BufferedReader reader = Files .newBufferedReader (customAreaFile , StandardCharsets .UTF_8 )) {
70
+ globalAreas .getFeatures ().addAll (mapper .readValue (reader , JsonFeatureCollection .class ).getFeatures ());
71
+ }
72
+ }
73
+ logger .info ("Will make " + globalAreas .getFeatures ().size () + " areas available to all custom profiles. Found in " + customAreasDirectory );
74
+ } catch (IOException e ) {
75
+ throw new UncheckedIOException (e );
76
+ }
77
+ }
78
+
79
+ List <Profile > newProfiles = resolveCustomModelFiles (customModelFolder , configuration .getProfiles (), globalAreas );
54
80
configuration .setProfiles (newProfiles );
55
81
56
82
graphHopper .init (configuration );
57
83
}
58
84
59
- public static List <Profile > resolveCustomModelFiles (String customModelFolder , List <Profile > profiles ) {
85
+ public static List <Profile > resolveCustomModelFiles (String customModelFolder , List <Profile > profiles , JsonFeatureCollection globalAreas ) {
60
86
ObjectMapper jsonOM = Jackson .newObjectMapper ();
61
87
List <Profile > newProfiles = new ArrayList <>();
62
88
for (Profile profile : profiles ) {
@@ -65,37 +91,47 @@ public static List<Profile> resolveCustomModelFiles(String customModelFolder, Li
65
91
continue ;
66
92
}
67
93
Object cm = profile .getHints ().getObject ("custom_model" , null );
94
+ CustomModel customModel ;
68
95
if (cm != null ) {
69
96
try {
70
97
// custom_model can be an object tree (read from config) or an object (e.g. from tests)
71
- CustomModel customModel = jsonOM .readValue (jsonOM .writeValueAsBytes (cm ), CustomModel .class );
98
+ customModel = jsonOM .readValue (jsonOM .writeValueAsBytes (cm ), CustomModel .class );
72
99
newProfiles .add (new CustomProfile (profile ).setCustomModel (customModel ));
73
- continue ;
74
100
} catch (Exception ex ) {
75
101
throw new RuntimeException ("Cannot load custom_model from " + cm + " for profile " + profile .getName ()
76
102
+ ". If you are trying to load from a file, use 'custom_model_file' instead." , ex );
77
103
}
78
- }
79
- String customModelFileName = profile .getHints ().getString ("custom_model_file" , "" );
80
- if (customModelFileName .isEmpty ())
81
- throw new IllegalArgumentException ("Missing 'custom_model' or 'custom_model_file' field in profile '"
82
- + profile .getName () + "'. To use default specify custom_model_file: empty" );
83
- if ("empty" .equals (customModelFileName ))
84
- newProfiles .add (new CustomProfile (profile ).setCustomModel (new CustomModel ()));
85
- else {
86
- if (customModelFileName .contains (File .separator ))
87
- throw new IllegalArgumentException ("Use custom_model_folder for the custom_model_file parent" );
88
- if (!customModelFileName .endsWith (".json" ))
89
- throw new IllegalArgumentException ("Yaml is no longer supported, see #2672. Use JSON with optional comments //" );
90
- try {
91
- // Somehow dropwizard makes it very hard to find out the folder of config.yml -> use an extra parameter for the folder
92
- String string = Helper .readJSONFileWithoutComments (Paths .get (customModelFolder ).resolve (customModelFileName ).toFile ().getAbsolutePath ());
93
- CustomModel customModel = jsonOM .readValue (string , CustomModel .class );
94
- newProfiles .add (new CustomProfile (profile ).setCustomModel (customModel ));
95
- } catch (Exception ex ) {
96
- throw new RuntimeException ("Cannot load custom_model from location " + customModelFileName + " for profile " + profile .getName (), ex );
104
+ } else {
105
+ String customModelFileName = profile .getHints ().getString ("custom_model_file" , "" );
106
+ if (customModelFileName .isEmpty ())
107
+ throw new IllegalArgumentException ("Missing 'custom_model' or 'custom_model_file' field in profile '"
108
+ + profile .getName () + "'. To use default specify custom_model_file: empty" );
109
+ if ("empty" .equals (customModelFileName ))
110
+ newProfiles .add (new CustomProfile (profile ).setCustomModel (customModel = new CustomModel ()));
111
+ else {
112
+ if (customModelFileName .contains (File .separator ))
113
+ throw new IllegalArgumentException ("Use custom_model_folder for the custom_model_file parent" );
114
+ if (!customModelFileName .endsWith (".json" ))
115
+ throw new IllegalArgumentException ("Yaml is no longer supported, see #2672. Use JSON with optional comments //" );
116
+ try {
117
+ // Somehow dropwizard makes it very hard to find out the folder of config.yml -> use an extra parameter for the folder
118
+ String string = Helper .readJSONFileWithoutComments (Paths .get (customModelFolder ).resolve (customModelFileName ).toFile ().getAbsolutePath ());
119
+ customModel = jsonOM .readValue (string , CustomModel .class );
120
+ newProfiles .add (new CustomProfile (profile ).setCustomModel (customModel ));
121
+ } catch (Exception ex ) {
122
+ throw new RuntimeException ("Cannot load custom_model from location " + customModelFileName + " for profile " + profile .getName (), ex );
123
+ }
97
124
}
98
125
}
126
+
127
+ // we can fill in all areas here as in the created template we include only the areas that are used in statements (see CustomModelParser)
128
+ for (JsonFeature feature : globalAreas .getFeatures ()) {
129
+ if (customModel .getAreas ().containsKey (feature .getId ()))
130
+ throw new IllegalArgumentException ("The area '" + feature .getId () + "' in profile configuration '"
131
+ + profile .getName () + "' cannot have same ID as global area." );
132
+ else
133
+ customModel .getAreas ().put (feature .getId (), feature );
134
+ }
99
135
}
100
136
return newProfiles ;
101
137
}
0 commit comments