|
19 | 19 |
|
20 | 20 | import com.graphhopper.json.Statement;
|
21 | 21 | import com.graphhopper.routing.ev.*;
|
22 |
| -import com.graphhopper.routing.util.EncodingManager; |
23 | 22 | import com.graphhopper.routing.weighting.TurnCostProvider;
|
24 | 23 | import com.graphhopper.util.*;
|
25 | 24 | import com.graphhopper.util.shapes.BBox;
|
@@ -71,7 +70,7 @@ private CustomModelParser() {
|
71 | 70 | /**
|
72 | 71 | * This method creates a weighting from a CustomModel that must limit the speed. Either as an
|
73 | 72 | * unconditional statement <code>{ "if": "true", "limit_to": "car_average_speed" }<code/> or as
|
74 |
| - * an if-else block. |
| 73 | + * an if-elseif-else group. |
75 | 74 | */
|
76 | 75 | public static CustomWeighting createWeighting(EncodedValueLookup lookup, TurnCostProvider turnCostProvider, CustomModel customModel) {
|
77 | 76 | if (customModel == null)
|
@@ -142,15 +141,15 @@ private static Class<?> createClazz(CustomModel customModel, EncodedValueLookup
|
142 | 141 | if (customModel.getSpeed().isEmpty())
|
143 | 142 | throw new IllegalArgumentException("At least one initial statement under 'speed' is required.");
|
144 | 143 |
|
145 |
| - List<Statement> firstBlock = splitIntoBlocks(customModel.getSpeed()).get(0); |
146 |
| - if (firstBlock.size() > 1) { |
147 |
| - Statement lastSt = firstBlock.get(firstBlock.size() - 1); |
148 |
| - if (lastSt.getOperation() != Statement.Op.LIMIT || lastSt.getKeyword() != Statement.Keyword.ELSE) |
149 |
| - throw new IllegalArgumentException("The first block needs to end with an 'else' (or contain a single unconditional 'if' statement)."); |
| 144 | + List<Statement> firstGroup = splitIntoGroup(customModel.getSpeed()).get(0); |
| 145 | + if (firstGroup.size() > 1) { |
| 146 | + Statement lastSt = firstGroup.get(firstGroup.size() - 1); |
| 147 | + if (lastSt.operation() != Statement.Op.LIMIT || lastSt.keyword() != Statement.Keyword.ELSE) |
| 148 | + throw new IllegalArgumentException("The first group needs to end with an 'else' (or contain a single unconditional 'if' statement)."); |
150 | 149 | } else {
|
151 |
| - Statement firstSt = firstBlock.get(0); |
152 |
| - if (!"true".equals(firstSt.getCondition()) || firstSt.getOperation() != Statement.Op.LIMIT || firstSt.getKeyword() != Statement.Keyword.IF) |
153 |
| - throw new IllegalArgumentException("The first block needs to contain a single unconditional 'if' statement (or end with an 'else')."); |
| 150 | + Statement firstSt = firstGroup.get(0); |
| 151 | + if (!"true".equals(firstSt.condition()) || firstSt.operation() != Statement.Op.LIMIT || firstSt.keyword() != Statement.Keyword.IF) |
| 152 | + throw new IllegalArgumentException("The first group needs to contain a single unconditional 'if' statement (or end with an 'else')."); |
154 | 153 | }
|
155 | 154 |
|
156 | 155 | Set<String> speedVariables = ValueExpressionVisitor.findVariables(customModel.getSpeed(), lookup);
|
@@ -191,27 +190,32 @@ public static List<String> findVariablesForEncodedValuesString(CustomModel model
|
191 | 190 | }
|
192 | 191 |
|
193 | 192 | private static void findVariablesForEncodedValuesString(List<Statement> statements, NameValidator nameValidator, ClassHelper classHelper) {
|
194 |
| - List<List<Statement>> blocks = CustomModelParser.splitIntoBlocks(statements); |
195 |
| - for (List<Statement> block : blocks) { |
196 |
| - for (Statement statement : block) { |
197 |
| - // ignore potential problems; collect only variables in this step |
198 |
| - ConditionalExpressionVisitor.parse(statement.getCondition(), nameValidator, classHelper); |
199 |
| - ValueExpressionVisitor.parse(statement.getValue(), nameValidator); |
| 193 | + List<List<Statement>> groups = CustomModelParser.splitIntoGroup(statements); |
| 194 | + for (List<Statement> group : groups) { |
| 195 | + for (Statement statement : group) { |
| 196 | + if (statement.isBlock()) { |
| 197 | + findVariablesForEncodedValuesString(statement.doBlock(), nameValidator, classHelper); |
| 198 | + } else { |
| 199 | + // ignore potential problems; collect only variables in this step |
| 200 | + ConditionalExpressionVisitor.parse(statement.condition(), nameValidator, classHelper); |
| 201 | + ValueExpressionVisitor.parse(statement.value(), nameValidator); |
| 202 | + } |
200 | 203 | }
|
201 | 204 | }
|
202 | 205 | }
|
203 | 206 |
|
204 | 207 | /**
|
205 |
| - * Splits the specified list into several list of statements starting with if |
| 208 | + * Splits the specified list into several lists of statements starting with if. |
| 209 | + * I.e. a group consists of one 'if' and zero or more 'else_if' and 'else' statements. |
206 | 210 | */
|
207 |
| - static List<List<Statement>> splitIntoBlocks(List<Statement> statements) { |
| 211 | + static List<List<Statement>> splitIntoGroup(List<Statement> statements) { |
208 | 212 | List<List<Statement>> result = new ArrayList<>();
|
209 |
| - List<Statement> block = null; |
| 213 | + List<Statement> group = null; |
210 | 214 | for (Statement st : statements) {
|
211 |
| - if (IF.equals(st.getKeyword())) result.add(block = new ArrayList<>()); |
212 |
| - if (block == null) |
213 |
| - throw new IllegalArgumentException("Every block must start with an if-statement"); |
214 |
| - block.add(st); |
| 215 | + if (IF.equals(st.keyword())) result.add(group = new ArrayList<>()); |
| 216 | + if (group == null) |
| 217 | + throw new IllegalArgumentException("Every group must start with an if-statement"); |
| 218 | + group.add(st); |
215 | 219 | }
|
216 | 220 | return result;
|
217 | 221 | }
|
@@ -406,36 +410,52 @@ private static List<Java.BlockStatement> verifyExpressions(StringBuilder express
|
406 | 410 | || name.startsWith(BACKWARD_PREFIX) && lookup.hasEncodedValue(name.substring(BACKWARD_PREFIX.length()));
|
407 | 411 | ClassHelper helper = key -> getReturnType(lookup.getEncodedValue(key, EncodedValue.class));
|
408 | 412 |
|
409 |
| - parseExpressions(expressions, nameInConditionValidator, info, createObjects, list, helper); |
| 413 | + parseExpressions(expressions, nameInConditionValidator, info, createObjects, list, helper, ""); |
| 414 | + expressions.append("return value;\n"); |
410 | 415 | return new Parser(new org.codehaus.janino.Scanner(info, new StringReader(expressions.toString()))).
|
411 | 416 | parseBlockStatements();
|
412 | 417 | }
|
413 | 418 |
|
414 | 419 | static void parseExpressions(StringBuilder expressions, NameValidator nameInConditionValidator,
|
415 | 420 | String exceptionInfo, Set<String> createObjects, List<Statement> list,
|
416 |
| - ClassHelper classHelper) { |
| 421 | + ClassHelper classHelper, String indentation) { |
417 | 422 |
|
418 | 423 | for (Statement statement : list) {
|
419 | 424 | // avoid parsing the RHS value expression again as we just did it to get the maximum values in createClazz
|
420 |
| - if (statement.getKeyword() == Statement.Keyword.ELSE) { |
421 |
| - if (!Helper.isEmpty(statement.getCondition())) |
422 |
| - throw new IllegalArgumentException("condition must be empty but was " + statement.getCondition()); |
423 |
| - |
424 |
| - expressions.append("else {").append(statement.getOperation().build(statement.getValue())).append("; }\n"); |
425 |
| - } else if (statement.getKeyword() == Statement.Keyword.ELSEIF || statement.getKeyword() == Statement.Keyword.IF) { |
426 |
| - ParseResult parseResult = ConditionalExpressionVisitor.parse(statement.getCondition(), nameInConditionValidator, classHelper); |
| 425 | + if (statement.keyword() == Statement.Keyword.ELSE) { |
| 426 | + if (!Helper.isEmpty(statement.condition())) |
| 427 | + throw new IllegalArgumentException("condition must be empty but was " + statement.condition()); |
| 428 | + |
| 429 | + expressions.append(indentation); |
| 430 | + if (statement.isBlock()) { |
| 431 | + expressions.append("else {"); |
| 432 | + parseExpressions(expressions, nameInConditionValidator, exceptionInfo, createObjects, statement.doBlock(), classHelper, indentation + " "); |
| 433 | + expressions.append(indentation).append("}\n"); |
| 434 | + } else { |
| 435 | + expressions.append("else {").append(statement.operation().build(statement.value())).append("; }\n"); |
| 436 | + } |
| 437 | + } else if (statement.keyword() == Statement.Keyword.ELSEIF || statement.keyword() == Statement.Keyword.IF) { |
| 438 | + ParseResult parseResult = ConditionalExpressionVisitor.parse(statement.condition(), nameInConditionValidator, classHelper); |
427 | 439 | if (!parseResult.ok)
|
428 |
| - throw new IllegalArgumentException(exceptionInfo + " invalid condition \"" + statement.getCondition() + "\"" + |
| 440 | + throw new IllegalArgumentException(exceptionInfo + " invalid condition \"" + statement.condition() + "\"" + |
429 | 441 | (parseResult.invalidMessage == null ? "" : ": " + parseResult.invalidMessage));
|
430 | 442 | createObjects.addAll(parseResult.guessedVariables);
|
431 |
| - if (statement.getKeyword() == Statement.Keyword.ELSEIF) |
432 |
| - expressions.append("else "); |
433 |
| - expressions.append("if (").append(parseResult.converted).append(") {").append(statement.getOperation().build(statement.getValue())).append(";}\n"); |
| 443 | + if (statement.keyword() == Statement.Keyword.ELSEIF) |
| 444 | + expressions.append(indentation).append("else "); |
| 445 | + |
| 446 | + expressions.append(indentation); |
| 447 | + if (statement.isBlock()) { |
| 448 | + expressions.append("if (").append(parseResult.converted).append(") {\n"); |
| 449 | + parseExpressions(expressions, nameInConditionValidator, exceptionInfo, createObjects, statement.doBlock(), classHelper, indentation + " "); |
| 450 | + expressions.append(indentation).append("}\n"); |
| 451 | + } else { |
| 452 | + expressions.append("if (").append(parseResult.converted).append(") {"). |
| 453 | + append(statement.operation().build(statement.value())).append(";}\n"); |
| 454 | + } |
434 | 455 | } else {
|
435 | 456 | throw new IllegalArgumentException("The statement must be either 'if', 'else_if' or 'else'");
|
436 | 457 | }
|
437 | 458 | }
|
438 |
| - expressions.append("return value;\n"); |
439 | 459 | }
|
440 | 460 |
|
441 | 461 | /**
|
|
0 commit comments