Skip to content

Commit b8c64be

Browse files
authored
EncodingManager refactoring (graphhopper#1546)
* EncodingManager refactoring * avoid name clash with new TagParser
1 parent 022697d commit b8c64be

File tree

83 files changed

+358
-372
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+358
-372
lines changed

core/files/changelog.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
0.12
2+
refactoring of EncodingManager to use builder pattern. Migration should be simple. Replace new EncodingManager with EncodingManager.create
3+
EncodingManager.supports renames to hasEncoder
24
big refactoring #1447: to increase 64bit limit of flags, make reverse direction handling easier, to allow shared EncodedValues,
35
remove reverseFlags method, much simpler property access, simplify FlagEncoder (maybe even deprecate this interface at a later stage)
46
moved shp-reader into separate repository: https://github.com/graphhopper/graphhopper-reader-shp

core/src/main/java/com/graphhopper/GraphHopper.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ public GraphHopper init(CmdArgs args) {
548548
int bytesForFlags = args.getInt("graph.bytes_for_flags", 4);
549549
String flagEncodersStr = args.get("graph.flag_encoders", "");
550550
if (!flagEncodersStr.isEmpty())
551-
setEncodingManager(new EncodingManager(flagEncoderFactory, flagEncodersStr, bytesForFlags));
551+
setEncodingManager(EncodingManager.create(flagEncoderFactory, flagEncodersStr, bytesForFlags));
552552

553553
if (args.get("graph.locktype", "native").equals("simple"))
554554
lockFactory = new SimpleFSLockFactory();
@@ -881,7 +881,7 @@ public void postProcessing() {
881881
}
882882

883883
private void interpolateBridgesAndOrTunnels() {
884-
if (ghStorage.getEncodingManager().supports("generic")) {
884+
if (ghStorage.getEncodingManager().hasEncoder("generic")) {
885885
final FlagEncoder genericFlagEncoder = ghStorage.getEncodingManager()
886886
.getEncoder("generic");
887887
if (!(genericFlagEncoder instanceof DataFlagEncoder)) {
@@ -983,7 +983,7 @@ public List<Path> calcPaths(GHRequest request, GHResponse ghRsp) {
983983
Lock readLock = readWriteLock.readLock();
984984
readLock.lock();
985985
try {
986-
if (!encodingManager.supports(vehicle))
986+
if (!encodingManager.hasEncoder(vehicle))
987987
throw new IllegalArgumentException("Vehicle not supported: " + vehicle + ". Supported are: " + encodingManager.toString());
988988

989989
HintsMap hints = request.getHints();

core/src/main/java/com/graphhopper/routing/profiles/EncodedValueLookup.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ public interface EncodedValueLookup {
2929

3030
ObjectEncodedValue getObjectEncodedValue(String key);
3131

32-
boolean supports(String key);
32+
boolean hasEncoder(String key);
3333
}

core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ public boolean equals(Object obj) {
310310
/**
311311
* @return the speed in km/h
312312
*/
313-
protected double parseSpeed(String str) {
313+
public static double parseSpeed(String str) {
314314
if (Helper.isEmpty(str))
315315
return -1;
316316

@@ -537,13 +537,13 @@ protected boolean isAccept(long internalFlags) {
537537

538538
public final DecimalEncodedValue getAverageSpeedEnc() {
539539
if (speedEncoder == null)
540-
throw new NullPointerException("FlagEncoder not yet initialized");
540+
throw new NullPointerException("FlagEncoder " + toString() + " not yet initialized");
541541
return speedEncoder;
542542
}
543543

544544
public final BooleanEncodedValue getAccessEnc() {
545545
if (accessEnc == null)
546-
throw new NullPointerException("FlagEncoder not yet initialized");
546+
throw new NullPointerException("FlagEncoder " + toString() + " not yet initialized");
547547
return accessEnc;
548548
}
549549

@@ -638,7 +638,7 @@ public boolean supports(Class<?> feature) {
638638
}
639639

640640
@Override
641-
public boolean supports(String key) {
642-
return encodedValueLookup.supports(key);
641+
public boolean hasEncoder(String key) {
642+
return encodedValueLookup.hasEncoder(key);
643643
}
644644
}

core/src/main/java/com/graphhopper/routing/util/EncodingManager.java

Lines changed: 115 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@
3535

3636
/**
3737
* Manager class to register encoder, assign their flag values and check objects with all encoders
38-
* during parsing.
38+
* during parsing. Create one via:
3939
* <p>
40+
* EncodingManager.start(4).add(new CarFlagEncoder()).build();
4041
*
4142
* @author Peter Karich
4243
* @author Nop
@@ -46,7 +47,7 @@ public class EncodingManager implements EncodedValueLookup {
4647
private static final String WAY_ERR = "Decrease the number of vehicles or increase the flags to take long via graph.bytes_for_flags: 8";
4748
private final List<AbstractFlagEncoder> edgeEncoders = new ArrayList<>();
4849
private final Map<String, EncodedValue> encodedValueMap = new LinkedHashMap<>();
49-
private final Map<EncodedValue, OSMTagParser> sharedEncodedValueMap = new LinkedHashMap<>();
50+
private final Map<EncodedValue, TagParser> sharedEncodedValueMap = new LinkedHashMap<>();
5051
private final int bitsForEdgeFlags;
5152
private final int bitsForTurnFlags = 8 * 4;
5253
private int nextNodeBit = 0;
@@ -63,61 +64,139 @@ public class EncodingManager implements EncodedValueLookup {
6364
*
6465
* @param flagEncodersStr comma delimited list of encoders. The order does not matter.
6566
*/
66-
public EncodingManager(String flagEncodersStr) {
67-
this(flagEncodersStr, 4);
67+
public static EncodingManager create(String flagEncodersStr) {
68+
return create(flagEncodersStr, 4);
6869
}
6970

70-
public EncodingManager(String flagEncodersStr, int bytesForEdgeFlags) {
71-
this(FlagEncoderFactory.DEFAULT, flagEncodersStr, bytesForEdgeFlags);
71+
public static EncodingManager create(String flagEncodersStr, int bytesForEdgeFlags) {
72+
return create(FlagEncoderFactory.DEFAULT, flagEncodersStr, bytesForEdgeFlags);
7273
}
7374

74-
public EncodingManager(FlagEncoderFactory factory, String flagEncodersStr, int bytesForEdgeFlags) {
75-
this(parseEncoderString(factory, flagEncodersStr), bytesForEdgeFlags);
75+
public static EncodingManager create(FlagEncoderFactory factory, String flagEncodersStr, int bytesForEdgeFlags) {
76+
return create(parseEncoderString(factory, flagEncodersStr), bytesForEdgeFlags);
7677
}
7778

7879
/**
7980
* Instantiate manager with the given list of encoders.
8081
*
8182
* @param flagEncoders comma delimited list of encoders. The order does not matter.
8283
*/
83-
public EncodingManager(FlagEncoder... flagEncoders) {
84-
this(Arrays.asList(flagEncoders));
84+
public static EncodingManager create(FlagEncoder... flagEncoders) {
85+
return create(Arrays.asList(flagEncoders));
8586
}
8687

8788
/**
8889
* Instantiate manager with the given list of encoders.
8990
*
9091
* @param flagEncoders comma delimited list of encoders. The order does not matter.
9192
*/
92-
public EncodingManager(List<? extends FlagEncoder> flagEncoders) {
93-
this(flagEncoders, 4);
93+
public static EncodingManager create(List<? extends FlagEncoder> flagEncoders) {
94+
return create(flagEncoders, 4);
9495
}
9596

96-
public EncodingManager(List<? extends FlagEncoder> flagEncoders, int bytesForEdgeFlags) {
97-
if (bytesForEdgeFlags <= 0 || (bytesForEdgeFlags / 4) * 4 != bytesForEdgeFlags)
98-
throw new IllegalStateException("For 'edge flags' only a multiple of 4 is supported");
97+
public static EncodingManager create(List<? extends FlagEncoder> flagEncoders, int bytesForEdgeFlags) {
98+
Builder builder = new Builder(bytesForEdgeFlags);
99+
for (FlagEncoder flagEncoder : flagEncoders) {
100+
builder.add(flagEncoder);
101+
}
102+
return builder.build();
103+
}
99104

100-
this.bitsForEdgeFlags = bytesForEdgeFlags * 8;
105+
/**
106+
* Create the EncodingManager from the provided GraphHopper location. Throws an
107+
* IllegalStateException if it fails. Used if no EncodingManager specified on load.
108+
*/
109+
public static EncodingManager create(FlagEncoderFactory factory, String ghLoc) {
110+
Directory dir = new RAMDirectory(ghLoc, true);
111+
StorableProperties properties = new StorableProperties(dir);
112+
if (!properties.loadExisting())
113+
throw new IllegalStateException("Cannot load properties to fetch EncodingManager configuration at: "
114+
+ dir.getLocation());
115+
116+
// check encoding for compatibility
117+
properties.checkVersions(false);
118+
String acceptStr = properties.get("graph.flag_encoders");
119+
120+
if (acceptStr.isEmpty())
121+
throw new IllegalStateException("EncodingManager was not configured. And no one was found in the graph: "
122+
+ dir.getLocation());
123+
124+
int bytesForFlags = 4;
125+
try {
126+
bytesForFlags = Integer.parseInt(properties.get("graph.bytes_for_flags"));
127+
} catch (NumberFormatException ex) {
128+
}
129+
return create(factory, acceptStr, bytesForFlags);
130+
}
131+
132+
/**
133+
* Starts the build process of an EncodingManager
134+
*/
135+
public static Builder start() {
136+
return new Builder(4);
137+
}
138+
139+
private EncodingManager(int bytes) {
140+
if (bytes <= 0 || (bytes / 4) * 4 != bytes)
141+
throw new IllegalStateException("bytesForEdgeFlags can be only a multiple of 4");
142+
143+
this.bitsForEdgeFlags = bytes * 8;
101144
this.config = new EncodedValue.InitializerConfig();
102-
final BooleanEncodedValue roundaboutEnc = new SimpleBooleanEncodedValue("roundabout", false);
103-
sharedEncodedValueMap.put(roundaboutEnc, new OSMTagParser() {
104-
@Override
105-
public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, long allowed, long relationFlags) {
106-
boolean isRoundabout = way.hasTag("junction", "roundabout") || way.hasTag("junction", "circular");
107-
if (isRoundabout)
108-
roundaboutEnc.setBool(false, edgeFlags, true);
109-
return edgeFlags;
145+
}
146+
147+
public static class Builder {
148+
private final EncodingManager em;
149+
private boolean buildCalled = false;
150+
151+
public Builder(int bytes) {
152+
em = new EncodingManager(bytes);
153+
final BooleanEncodedValue roundaboutEnc = new SimpleBooleanEncodedValue("roundabout", false);
154+
put(roundaboutEnc, new TagParser() {
155+
@Override
156+
public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, long allowed, long relationFlags) {
157+
boolean isRoundabout = way.hasTag("junction", "roundabout") || way.hasTag("junction", "circular");
158+
if (isRoundabout)
159+
roundaboutEnc.setBool(false, edgeFlags, true);
160+
return edgeFlags;
161+
}
162+
});
163+
}
164+
165+
/**
166+
* For backward compatibility provide a way to add multiple FlagEncoders
167+
*/
168+
public Builder addAll(FlagEncoderFactory factory, String flagEncodersStr) {
169+
for (FlagEncoder fe : parseEncoderString(factory, flagEncodersStr)) {
170+
add(fe);
110171
}
111-
});
112-
for (EncodedValue ev : sharedEncodedValueMap.keySet()) {
113-
addEncodedValue(ev);
172+
return this;
114173
}
115-
for (FlagEncoder flagEncoder : flagEncoders) {
116-
registerEncoder((AbstractFlagEncoder) flagEncoder);
174+
175+
public Builder add(FlagEncoder encoder) {
176+
em.addEncoder((AbstractFlagEncoder) encoder);
177+
return this;
117178
}
118179

119-
if (edgeEncoders.isEmpty())
120-
throw new IllegalStateException("No vehicles found");
180+
public Builder add(EncodedValue encodedValue) {
181+
em.addEncodedValue(encodedValue);
182+
return this;
183+
}
184+
185+
public Builder put(EncodedValue encodedValue, TagParser tagParser) {
186+
add(encodedValue);
187+
em.sharedEncodedValueMap.put(encodedValue, tagParser);
188+
return this;
189+
}
190+
191+
public EncodingManager build() {
192+
if (buildCalled)
193+
throw new IllegalStateException("Cannot call Builder.build() twice");
194+
if (em.encodedValueMap.isEmpty())
195+
throw new IllegalStateException("No EncodedValues found");
196+
197+
buildCalled = true;
198+
return em;
199+
}
121200
}
122201

123202
static List<FlagEncoder> parseEncoderString(FlagEncoderFactory factory, String encoderList) {
@@ -159,38 +238,11 @@ static String fixWayName(String str) {
159238
return str.replaceAll(";[ ]*", ", ");
160239
}
161240

162-
/**
163-
* Create the EncodingManager from the provided GraphHopper location. Throws an
164-
* IllegalStateException if it fails. Used if no EncodingManager specified on load.
165-
*/
166-
public static EncodingManager create(FlagEncoderFactory factory, String ghLoc) {
167-
Directory dir = new RAMDirectory(ghLoc, true);
168-
StorableProperties properties = new StorableProperties(dir);
169-
if (!properties.loadExisting())
170-
throw new IllegalStateException("Cannot load properties to fetch EncodingManager configuration at: "
171-
+ dir.getLocation());
172-
173-
// check encoding for compatibility
174-
properties.checkVersions(false);
175-
String acceptStr = properties.get("graph.flag_encoders");
176-
177-
if (acceptStr.isEmpty())
178-
throw new IllegalStateException("EncodingManager was not configured. And no one was found in the graph: "
179-
+ dir.getLocation());
180-
181-
int bytesForFlags = 4;
182-
try {
183-
bytesForFlags = Integer.parseInt(properties.get("graph.bytes_for_flags"));
184-
} catch (NumberFormatException ex) {
185-
}
186-
return new EncodingManager(factory, acceptStr, bytesForFlags);
187-
}
188-
189241
public int getBytesForFlags() {
190242
return bitsForEdgeFlags / 8;
191243
}
192244

193-
private void registerEncoder(AbstractFlagEncoder encoder) {
245+
private void addEncoder(AbstractFlagEncoder encoder) {
194246
if (encoder.isRegistered())
195247
throw new IllegalStateException("You must not register a FlagEncoder (" + encoder.toString() + ") twice!");
196248

@@ -243,7 +295,7 @@ private void addEncodedValue(EncodedValue ev) {
243295
/**
244296
* @return true if the specified encoder is found
245297
*/
246-
public boolean supports(String encoder) {
298+
public boolean hasEncoder(String encoder) {
247299
return getEncoder(encoder, false) != null;
248300
}
249301

@@ -290,7 +342,7 @@ public long handleRelationTags(long oldRelationFlags, ReaderRelation relation) {
290342
*/
291343
public IntsRef handleWayTags(ReaderWay way, long includeWay, long relationFlags) {
292344
IntsRef edgeFlags = createEdgeFlags();
293-
for (OSMTagParser parser : sharedEncodedValueMap.values()) {
345+
for (TagParser parser : sharedEncodedValueMap.values()) {
294346
parser.handleWayTags(edgeFlags, way, includeWay, relationFlags);
295347
}
296348
for (AbstractFlagEncoder encoder : edgeEncoders) {
@@ -466,7 +518,7 @@ public ObjectEncodedValue getObjectEncodedValue(String key) {
466518
public <T extends EncodedValue> T getEncodedValue(String key, Class<T> encodedValueType) {
467519
EncodedValue ev = encodedValueMap.get(key);
468520
if (ev == null)
469-
throw new IllegalArgumentException("Cannot find encoded value " + key + " in collection: " + ev);
521+
throw new IllegalArgumentException("Cannot find EncodedValue " + key + " in collection: " + ev);
470522
return (T) ev;
471523
}
472524

@@ -479,8 +531,7 @@ public static final String getKey(FlagEncoder encoder, String str) {
479531
return encoder.toString() + "." + str;
480532
}
481533

482-
// for now keep private as public IntsRef is too ugly and relationFlags is unclear
483-
interface OSMTagParser {
534+
public interface TagParser {
484535
IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, long allowed, long relationFlags);
485536
}
486537
}

core/src/main/java/com/graphhopper/storage/CHGraph.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
* Extended graph interface which supports Contraction Hierarchies. Ie. storing and retrieving the
3030
* levels for a node and creating shortcuts, which are additional 'artificial' edges to speedup
3131
* traversal in certain cases.
32-
* <p>
3332
*
3433
* @author Peter Karich
3534
*/

core/src/main/java/com/graphhopper/storage/GraphHopperStorage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public GraphHopperStorage(List<? extends Weighting> nodeBasedCHWeightings, List<
6565
throw new IllegalArgumentException("GraphExtension cannot be null, use NoOpExtension");
6666

6767
if (encodingManager == null)
68-
throw new IllegalArgumentException("EncodingManager needs to be non-null since 0.7. Create one using new EncodingManager or EncodingManager.create(flagEncoderFactory, ghLocation)");
68+
throw new IllegalArgumentException("EncodingManager needs to be non-null since 0.7. Create one using EncodingManager.create or EncodingManager.create(flagEncoderFactory, ghLocation)");
6969

7070
this.encodingManager = encodingManager;
7171
this.dir = dir;

core/src/test/java/com/graphhopper/GraphHopperAPITest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* @author Peter Karich
4343
*/
4444
public class GraphHopperAPITest {
45-
final EncodingManager encodingManager = new EncodingManager("car");
45+
final EncodingManager encodingManager = EncodingManager.create("car");
4646

4747
void initGraph(GraphHopperStorage graph) {
4848
NodeAccess na = graph.getNodeAccess();

core/src/test/java/com/graphhopper/reader/PrincetonReaderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* @author Peter Karich
3838
*/
3939
public class PrincetonReaderTest {
40-
private EncodingManager encodingManager = new EncodingManager("car");
40+
private EncodingManager encodingManager = EncodingManager.create("car");
4141
private EdgeFilter carOutEdges = DefaultEdgeFilter.outEdges(encodingManager.getEncoder("car"));
4242

4343
@Test

core/src/test/java/com/graphhopper/reader/dem/AbstractEdgeElevationInterpolatorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public abstract class AbstractEdgeElevationInterpolatorTest {
5252
public void setUp() {
5353
dataFlagEncoder = new DataFlagEncoder();
5454
graph = new GraphHopperStorage(new RAMDirectory(),
55-
new EncodingManager(Arrays.asList(dataFlagEncoder, new FootFlagEncoder()),
55+
EncodingManager.create(Arrays.asList(dataFlagEncoder, new FootFlagEncoder()),
5656
8),
5757
true, new GraphExtension.NoOpExtension()).create(100);
5858

0 commit comments

Comments
 (0)