|
15 | 15 | import com.google.common.base.Predicate; |
16 | 16 | import com.google.common.base.Splitter; |
17 | 17 | import com.google.common.collect.*; |
| 18 | +import com.google.common.net.UrlEscapers; |
18 | 19 | import edu.umd.cs.findbugs.annotations.NonNull; |
19 | 20 | import edu.umd.cs.findbugs.annotations.Nullable; |
20 | 21 | import io.jooby.MediaType; |
@@ -46,13 +47,8 @@ protected String doApply( |
46 | 47 | int lineNumber) |
47 | 48 | throws Exception { |
48 | 49 | var options = args(args); |
49 | | - var method = |
50 | | - Optional.of(options.removeAll("-X")) |
51 | | - .map(Collection::iterator) |
52 | | - .filter(Iterator::hasNext) |
53 | | - .map(Iterator::next) |
54 | | - .orElse(operation.getMethod()) |
55 | | - .toUpperCase(); |
| 50 | + var method = removeOption(options, "-X", operation.getMethod()).toUpperCase(); |
| 51 | + var language = removeOption(options, "language", ""); |
56 | 52 | /* Accept/Content-Type: */ |
57 | 53 | var addAccept = true; |
58 | 54 | var addContentType = true; |
@@ -111,11 +107,21 @@ protected String doApply( |
111 | 107 | .collect(Collectors.joining("&", "?", "")); |
112 | 108 | } |
113 | 109 | options.put("-X", method + " '" + url + "'"); |
114 | | - var optionString = toString(options); |
115 | | - snippetContext.put("options", optionString); |
| 110 | + var optionsString = toString(options); |
| 111 | + snippetContext.put("options", optionsString); |
| 112 | + snippetContext.put("language", language); |
116 | 113 | return resolver.apply(id(), snippetContext); |
117 | 114 | } |
118 | 115 |
|
| 116 | + @NonNull private static String removeOption( |
| 117 | + Multimap<String, String> options, String name, String defaultValue) { |
| 118 | + return Optional.of(options.removeAll(name)) |
| 119 | + .map(Collection::iterator) |
| 120 | + .filter(Iterator::hasNext) |
| 121 | + .map(Iterator::next) |
| 122 | + .orElse(defaultValue); |
| 123 | + } |
| 124 | + |
119 | 125 | @NonNull private static Stream<Map.Entry<String, String>> encodeUrlParameter(List<Parameter> query) { |
120 | 126 | return query.stream() |
121 | 127 | .flatMap( |
@@ -272,6 +278,49 @@ protected String doApply( |
272 | 278 | return resolver.apply(id(), snippetContext); |
273 | 279 | } |
274 | 280 | }, |
| 281 | + path { |
| 282 | + @Override |
| 283 | + protected String doApply( |
| 284 | + SnippetResolver resolver, |
| 285 | + OperationExt operation, |
| 286 | + Map<String, Object> snippetContext, |
| 287 | + Map<String, Object> args, |
| 288 | + PebbleTemplate self, |
| 289 | + EvaluationContext context, |
| 290 | + int lineNumber) { |
| 291 | + var namedArgs = positionalArgs(args); |
| 292 | + // Path |
| 293 | + var path = parameters(operation, p -> "path".equals(p.getIn())); |
| 294 | + var pathParams = new HashMap<String, Object>(); |
| 295 | + path.forEach( |
| 296 | + p -> { |
| 297 | + pathParams.put( |
| 298 | + p.getName(), namedArgs.getOrDefault(p.getName(), "{" + p.getName() + "}")); |
| 299 | + }); |
| 300 | + // QueryString |
| 301 | + var query = |
| 302 | + parameters( |
| 303 | + operation, |
| 304 | + p -> |
| 305 | + "query".equals(p.getIn()) |
| 306 | + && (namedArgs.isEmpty() || namedArgs.containsKey(p.getName()))); |
| 307 | + var queryString = |
| 308 | + query.isEmpty() |
| 309 | + ? "" |
| 310 | + : query.stream() |
| 311 | + .map( |
| 312 | + it -> { |
| 313 | + var value = |
| 314 | + namedArgs.getOrDefault( |
| 315 | + it.getName(), SchemaData.shemaType(it.getSchema())); |
| 316 | + return it.getName() |
| 317 | + + "=" |
| 318 | + + UrlEscapers.urlFragmentEscaper().escape(value.toString()); |
| 319 | + }) |
| 320 | + .collect(Collectors.joining("&", "?", "")); |
| 321 | + return operation.getPath(pathParams) + queryString; |
| 322 | + } |
| 323 | + }, |
275 | 324 | pathParameters { |
276 | 325 | @Override |
277 | 326 | protected String doApply( |
@@ -406,7 +455,7 @@ protected final String id() { |
406 | 455 |
|
407 | 456 | @Override |
408 | 457 | public List<String> getArgumentNames() { |
409 | | - return List.of("code"); |
| 458 | + return null; |
410 | 459 | } |
411 | 460 |
|
412 | 461 | protected abstract String doApply( |
@@ -465,10 +514,10 @@ protected ResponseExt responseByStatusCode( |
465 | 514 |
|
466 | 515 | protected Map<String, Object> newSnippetContext(String serverUrl, OperationExt operation) { |
467 | 516 | Map<String, Object> map = new HashMap<>(); |
468 | | - map.put("pattern", operation.getPattern()); |
469 | | - map.put("path", operation.getPattern()); |
| 517 | + map.put("pattern", operation.getPath()); |
| 518 | + map.put("path", operation.getPath()); |
470 | 519 | map.put("method", operation.getMethod()); |
471 | | - map.put("url", serverUrl + operation.getPattern()); |
| 520 | + map.put("url", serverUrl + operation.getPath()); |
472 | 521 | var requestHeaders = ArrayListMultimap.<String, String>create(); |
473 | 522 | var responseHeaders = ArrayListMultimap.<String, String>create(); |
474 | 523 | var headerParams = |
@@ -524,14 +573,17 @@ protected List<Map<String, String>> schemaToTable(Schema<?> schema, EvaluationCo |
524 | 573 | return fields; |
525 | 574 | } |
526 | 575 |
|
| 576 | + protected List<Parameter> parameters(OperationExt operation, Predicate<Parameter> predicate) { |
| 577 | + return Optional.ofNullable(operation.getParameters()).orElse(List.of()).stream() |
| 578 | + .filter(predicate) |
| 579 | + .sorted(Comparator.comparing(Parameter::getName)) |
| 580 | + .toList(); |
| 581 | + } |
| 582 | + |
527 | 583 | protected List<Map<String, String>> parametersToTable( |
528 | 584 | OperationExt operation, Predicate<Parameter> predicate) { |
529 | 585 | List<Map<String, String>> fields = new ArrayList<>(); |
530 | | - var parameters = |
531 | | - Optional.ofNullable(operation.getParameters()).orElse(List.of()).stream() |
532 | | - .filter(predicate) |
533 | | - .sorted(Comparator.comparing(Parameter::getName)) |
534 | | - .toList(); |
| 586 | + var parameters = parameters(operation, predicate); |
535 | 587 | parameters.forEach( |
536 | 588 | it -> { |
537 | 589 | var schema = it.getSchema(); |
@@ -601,27 +653,36 @@ protected Multimap<CharSequence, String> parseHeaders(Collection<String> headers |
601 | 653 | protected static final Set<String> READ_METHODS = Set.of("GET", "HEAD"); |
602 | 654 |
|
603 | 655 | protected String toString(Multimap<String, String> options) { |
604 | | - if (options.isEmpty()) { |
605 | | - return ""; |
606 | | - } |
607 | 656 | var sb = new StringBuilder(); |
608 | 657 | var separator = "\\\n"; |
609 | 658 | var tabSize = id().length() + 1; |
610 | | - options.forEach( |
611 | | - (k, v) -> { |
612 | | - if (!sb.isEmpty()) { |
613 | | - sb.append(" ".repeat(tabSize)); |
614 | | - } |
615 | | - sb.append(k); |
616 | | - if (v != null && !v.isEmpty()) { |
617 | | - sb.append(" ").append(v); |
618 | | - } |
619 | | - sb.append(separator); |
620 | | - }); |
| 659 | + for (Map.Entry<String, String> entry : options.entries()) { |
| 660 | + var k = entry.getKey(); |
| 661 | + var v = entry.getValue(); |
| 662 | + if (!sb.isEmpty()) { |
| 663 | + sb.append(" ".repeat(tabSize)); |
| 664 | + } |
| 665 | + sb.append(k); |
| 666 | + if (v != null && !v.isEmpty()) { |
| 667 | + sb.append(" ").append(v); |
| 668 | + } |
| 669 | + sb.append(separator); |
| 670 | + } |
621 | 671 | sb.setLength(sb.length() - separator.length()); |
622 | 672 | return sb.toString(); |
623 | 673 | } |
624 | 674 |
|
| 675 | + protected Map<String, Object> positionalArgs(Map<String, Object> args) { |
| 676 | + var optionList = new ArrayList<>(args.values()); |
| 677 | + Map<String, Object> result = new LinkedHashMap<>(); |
| 678 | + for (int i = 0; i < optionList.size(); i += 2) { |
| 679 | + var key = optionList.get(i).toString(); |
| 680 | + var value = optionList.get(i + 1); |
| 681 | + result.put(key, value); |
| 682 | + } |
| 683 | + return result; |
| 684 | + } |
| 685 | + |
625 | 686 | protected Multimap<String, String> args(Map<String, Object> args) { |
626 | 687 | Multimap<String, String> result = LinkedHashMultimap.create(); |
627 | 688 | var optionList = new ArrayList<>(args.values()); |
|
0 commit comments