Skip to content

Commit 97bd024

Browse files
authored
Merge pull request GIScience#33 from GIScience/ors_0.13-fix_conditional_access
Resolve default access of conditional edges at graph build time
2 parents 3f4a67b + a269e68 commit 97bd024

21 files changed

+558
-250
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package com.graphhopper.reader;
19+
20+
/**
21+
* @author Andrzej Oles
22+
*/
23+
public interface ConditionalInspector {
24+
boolean hasLazyEvaluatedConditions();
25+
26+
String getTagValue();
27+
}

core/src/main/java/com/graphhopper/reader/ConditionalSpeedInspector.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@
2020
/**
2121
* @author Andrzej Oles
2222
*/
23-
public interface ConditionalSpeedInspector {
23+
public interface ConditionalSpeedInspector extends ConditionalInspector{
2424
boolean hasConditionalSpeed(ReaderWay way);
25-
26-
boolean isConditionLazyEvaluated();
27-
28-
String getTagValue();
2925
}

core/src/main/java/com/graphhopper/reader/ConditionalTagInspector.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,8 @@
2020
/**
2121
* @author Peter Karich
2222
*/
23-
public interface ConditionalTagInspector {
23+
public interface ConditionalTagInspector extends ConditionalInspector {
2424
boolean isRestrictedWayConditionallyPermitted(ReaderWay way);
2525

2626
boolean isPermittedWayConditionallyRestricted(ReaderWay way);
27-
28-
boolean isConditionLazyEvaluated();
29-
30-
String getTagValue();
3127
}

core/src/main/java/com/graphhopper/reader/osm/conditional/ConditionalOSMSpeedInspector.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class ConditionalOSMSpeedInspector implements ConditionalSpeedInspector {
3939
private boolean enabledLogs = true;
4040

4141
private String val;
42+
private boolean isLazyEvaluated;
4243

4344
@Override
4445
public String getTagValue() {
@@ -71,10 +72,11 @@ public boolean hasConditionalSpeed(ReaderWay way) {
7172
if (val == null || val.isEmpty())
7273
continue;
7374
try {
74-
if (parser.checkCondition(val)) {
75-
val = parser.getRestrictions();
75+
ConditionalParser.Result result = parser.checkCondition(val);
76+
isLazyEvaluated = result.isLazyEvaluated();
77+
val = result.getRestrictions();
78+
if (result.isCheckPassed() || isLazyEvaluated)
7679
return true;
77-
}
7880
} catch (Exception e) {
7981
if (enabledLogs) {
8082
logger.warn("for way " + way.getId() + " could not parse the conditional value '" + val + "' of tag '" + tagToCheck + "'. Exception:" + e.getMessage());
@@ -85,8 +87,8 @@ public boolean hasConditionalSpeed(ReaderWay way) {
8587
}
8688

8789
@Override
88-
public boolean isConditionLazyEvaluated() {
89-
return parser.hasUnevaluatedRestrictions();
90+
public boolean hasLazyEvaluatedConditions() {
91+
return isLazyEvaluated;
9092
}
9193

9294
}

core/src/main/java/com/graphhopper/reader/osm/conditional/ConditionalOSMTagInspector.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,25 +80,24 @@ public boolean isPermittedWayConditionallyRestricted(ReaderWay way) {
8080
}
8181

8282
@Override
83-
public boolean isConditionLazyEvaluated() {
83+
public boolean hasLazyEvaluatedConditions() {
8484
return isLazyEvaluated;
8585
}
8686

8787
protected boolean applies(ReaderWay way, ConditionalParser parser) {
88-
8988
isLazyEvaluated = false;
9089
for (int index = 0; index < tagsToCheck.size(); index++) {
9190
String tagToCheck = tagsToCheck.get(index);
9291
val = way.getTag(tagToCheck);
9392
if (val == null || val.isEmpty())
9493
continue;
9594
try {
96-
if (parser.checkCondition(val)) {
97-
if (parser.hasUnevaluatedRestrictions())
98-
isLazyEvaluated = true;
99-
val = parser.getRestrictions();
100-
return true;
101-
}
95+
ConditionalParser.Result result = parser.checkCondition(val);
96+
isLazyEvaluated = result.isLazyEvaluated();
97+
val = result.getRestrictions();
98+
// allow the check result to be false but still have unevaluated conditions
99+
if (result.isCheckPassed() || isLazyEvaluated)
100+
return result.isCheckPassed();
102101
} catch (Exception e) {
103102
if (enabledLogs) {
104103
// log only if no date ala 21:00 as currently date and numbers do not support time precise restrictions

core/src/main/java/com/graphhopper/reader/osm/conditional/ConditionalParser.java

Lines changed: 144 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@ public class ConditionalParser {
4242
private final Set<String> restrictedValues;
4343
private final List<ConditionalValueParser> valueParsers = new ArrayList<>(5);
4444
private final boolean enabledLogs;
45-
46-
private String simpleValue;
47-
private String unevaluatedRestrictions = "";
48-
private Conditions unevaluatedConditions;
45+
private final String simpleValue;
4946

5047
public ConditionalParser(Set<String> restrictedValues) {
5148
this(restrictedValues, false);
@@ -55,12 +52,7 @@ public ConditionalParser(Set<String> restrictedValues, boolean enabledLogs) {
5552
// use map => key & type (date vs. double)
5653
this.restrictedValues = restrictedValues;
5754
this.enabledLogs = enabledLogs;
58-
59-
if (hasRestrictedValues()) {
60-
if (restrictedValues.contains("yes"))
61-
this.simpleValue = "yes";
62-
else this.simpleValue = "no";
63-
}
55+
this.simpleValue = hasRestrictedValues() && restrictedValues.contains("yes") ? "yes" : "no";
6456
}
6557

6658
public static ConditionalValueParser createNumberParser(final String assertKey, final Number obj) {
@@ -155,38 +147,112 @@ public ConditionalParser setConditionalValueParser(ConditionalValueParser vp) {
155147
}
156148

157149
// attempt to parse the value with any of the registered parsers
158-
private boolean checkAtomicCondition(Condition condition) throws ParseException {
159-
for (ConditionalValueParser valueParser : valueParsers) {
160-
ConditionalValueParser.ConditionState c = valueParser.checkCondition(condition);
161-
if (c.isValid()) {
162-
if (c.isEvaluated())
163-
return c.isCheckPassed();
164-
else { // condition could not be evaluated but might evaluate to true during query
165-
unevaluatedConditions.addCondition(c.getCondition());
166-
return true;
150+
private ParsedCondition checkAtomicCondition(Condition condition, ParsedCondition parsedCondition) throws ParseException {
151+
parsedCondition.reset();
152+
try {
153+
for (ConditionalValueParser valueParser : valueParsers) {
154+
ConditionalValueParser.ConditionState conditionState = valueParser.checkCondition(condition);
155+
if (conditionState.isValid()) {
156+
parsedCondition.setValid(true);
157+
if (conditionState.isEvaluated()) {
158+
parsedCondition.setEvaluated(true);
159+
parsedCondition.setCheckPassed(conditionState.isCheckPassed());
160+
break;
161+
} else { // condition could not be evaluated but might evaluate to true during query
162+
parsedCondition.setLazyEvaluated(true);
163+
parsedCondition.getLazyEvaluatedConditions().add(conditionState.getCondition());
164+
}
167165
}
168166
}
169167
}
170-
return false;
168+
catch (ParseException e) {
169+
throw e;
170+
}
171+
finally {
172+
return parsedCondition;
173+
}
174+
}
175+
176+
class ParsedCondition {
177+
private boolean valid;
178+
private boolean evaluated;
179+
private boolean checkPassed;
180+
private boolean lazyEvaluated;
181+
private ArrayList<Condition> lazyEvaluatedConditions = new ArrayList<Condition>();
182+
183+
void reset() {
184+
valid = evaluated = checkPassed = lazyEvaluated = false;
185+
}
186+
187+
void setValid(boolean valid) {
188+
this.valid = valid;
189+
}
190+
191+
void setEvaluated(boolean evaluated) {
192+
this.evaluated = evaluated;
193+
}
194+
195+
void setCheckPassed(boolean checkPassed) {
196+
this.checkPassed = checkPassed;
197+
}
198+
199+
void setLazyEvaluated(boolean lazyEvaluated) {
200+
this.lazyEvaluated = lazyEvaluated;
201+
}
202+
203+
boolean isValid() {
204+
return valid;
205+
}
206+
207+
boolean isEvaluated() {
208+
return evaluated;
209+
}
210+
211+
boolean isCheckPassed() {
212+
return checkPassed;
213+
}
214+
215+
boolean isLazyEvaluated() {
216+
return lazyEvaluated;
217+
}
218+
219+
boolean isInvalidOrFalse() {
220+
return !valid || (!lazyEvaluated && evaluated && !checkPassed);
221+
}
222+
223+
ArrayList<Condition> getLazyEvaluatedConditions() {
224+
return lazyEvaluatedConditions;
225+
}
171226
}
172227

173228
// all of the combined conditions need to be met
174-
private boolean checkCombinedCondition(List<Condition> conditions) throws ParseException {
229+
private ParsedCondition checkCombinedCondition(Restriction restriction) throws ParseException {
230+
ParsedCondition parsedCondition = new ParsedCondition();
175231
// combined conditions, must be all matched
176-
for (Condition condition: conditions) {
177-
if (!checkAtomicCondition(condition))
178-
return false;
232+
boolean checkPassed = true;
233+
boolean lazyEvaluated = false;
234+
for (Condition condition: restriction.getConditions()) {
235+
parsedCondition = checkAtomicCondition(condition, parsedCondition);
236+
checkPassed = checkPassed && parsedCondition.isCheckPassed();
237+
if (parsedCondition.isInvalidOrFalse()) {
238+
lazyEvaluated = false;
239+
break;
240+
}
241+
if (parsedCondition.isLazyEvaluated())
242+
lazyEvaluated = true;
179243
}
180-
return true;
244+
parsedCondition.setLazyEvaluated(lazyEvaluated);
245+
parsedCondition.setCheckPassed(checkPassed);
246+
return parsedCondition;
181247
}
182248

183249

184-
public boolean checkCondition(String tagValue) throws ParseException {
250+
public Result checkCondition(String tagValue) throws ParseException {
251+
Result result = new Result();
185252
if (tagValue == null || tagValue.isEmpty() || !tagValue.contains("@"))
186-
return false;
253+
return result;
187254

188255
ArrayList<Restriction> parsedRestrictions = new ArrayList<>();
189-
unevaluatedRestrictions = "";
190256

191257
try {
192258
ConditionalRestrictionParser parser = new ConditionalRestrictionParser(new ByteArrayInputStream(tagValue.getBytes()));
@@ -200,52 +266,40 @@ public boolean checkCondition(String tagValue) throws ParseException {
200266
String restrictionValue = restriction.getValue();
201267

202268
if (hasRestrictedValues()) {
203-
// check whether the encountered value is on the list
204-
if (!restrictedValues.contains(restrictionValue))
269+
if (restrictedValues.contains(restrictionValue))
270+
restrictionValue = simpleValue;
271+
else
205272
continue;
206273
}
207274
else {
208-
simpleValue = restrictionValue;
275+
result.setRestrictions(restrictionValue);
209276
}
210277

211-
List<Condition> conditions = restriction.getConditions();
212-
213-
unevaluatedConditions = new Conditions(new ArrayList<Condition>(), restriction.inParen());
278+
ParsedCondition parsedConditions = checkCombinedCondition(restriction);
279+
boolean checkPassed = parsedConditions.isCheckPassed();
280+
result.setCheckPassed(result.isCheckPassed() || checkPassed);
214281

215-
if (checkCombinedCondition(conditions)) {
216-
// check for unevaluated conditions
217-
if (unevaluatedConditions.getConditions().isEmpty()) {
218-
return true; // terminate once the first matching condition which can be fully evaluated is encountered
219-
}
220-
else {
221-
parsedRestrictions.add(new Restriction(simpleValue, unevaluatedConditions));
222-
}
282+
// check for unevaluated conditions
283+
if (!parsedConditions.isLazyEvaluated()) {
284+
if (checkPassed)
285+
return result; // terminate once the first matching condition which can be fully evaluated is encountered
286+
}
287+
else {
288+
parsedRestrictions.add(0, new Restriction(restrictionValue, new Conditions(parsedConditions.getLazyEvaluatedConditions(), restriction.inParen())));
223289
}
224290
}
225291
} catch (ch.poole.conditionalrestrictionparser.ParseException e) {
226292
if (enabledLogs)
227293
logger.warn("Parser exception for " + tagValue + " " + e.toString());
228-
return false;
229-
}
230-
// at this point either no matching restriction was found or the encountered restrictions need to be lazy evaluated
231-
if (parsedRestrictions.isEmpty()) {
232-
return false;
233-
}
234-
else {
235-
unevaluatedRestrictions = Util.restrictionsToString(parsedRestrictions);
236-
return true;
294+
return result;
237295
}
238-
}
239296

240-
public String getRestrictions() {
241-
if (hasUnevaluatedRestrictions())
242-
return unevaluatedRestrictions;
243-
else
244-
return simpleValue;
245-
}
297+
if (!parsedRestrictions.isEmpty()) {
298+
result.setRestrictions(Util.restrictionsToString(parsedRestrictions));
299+
result.setLazyEvaluated(true);
300+
}
246301

247-
public boolean hasUnevaluatedRestrictions() {
248-
return !unevaluatedRestrictions.isEmpty();
302+
return result;
249303
}
250304

251305
protected static double parseNumber(String str) {
@@ -260,4 +314,34 @@ protected static double parseNumber(String str) {
260314
private boolean hasRestrictedValues() {
261315
return !( restrictedValues==null || restrictedValues.isEmpty() );
262316
}
317+
318+
class Result {
319+
private boolean checkPassed;
320+
private boolean lazyEvaluated;
321+
private String restrictions;
322+
323+
boolean isCheckPassed() {
324+
return checkPassed;
325+
}
326+
327+
void setCheckPassed(boolean checkPassed) {
328+
this.checkPassed = checkPassed;
329+
}
330+
331+
boolean isLazyEvaluated() {
332+
return lazyEvaluated;
333+
}
334+
335+
void setLazyEvaluated(boolean lazyEvaluated) {
336+
this.lazyEvaluated = lazyEvaluated;
337+
}
338+
339+
String getRestrictions() {
340+
return restrictions;
341+
}
342+
343+
void setRestrictions(String restrictions) {
344+
this.restrictions = restrictions;
345+
}
346+
}
263347
}

0 commit comments

Comments
 (0)