1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.tools;
|
---|
3 |
|
---|
4 | import java.io.IOException;
|
---|
5 | import java.io.InputStreamReader;
|
---|
6 | import java.io.Reader;
|
---|
7 | import java.nio.charset.StandardCharsets;
|
---|
8 | import java.util.HashMap;
|
---|
9 |
|
---|
10 | import javax.script.Invocable;
|
---|
11 | import javax.script.ScriptEngine;
|
---|
12 | import javax.script.ScriptEngineManager;
|
---|
13 | import javax.script.ScriptException;
|
---|
14 |
|
---|
15 | import org.openstreetmap.josm.Main;
|
---|
16 |
|
---|
17 | /**
|
---|
18 | * Uses <a href="https://github.com/tyrasd/overpass-wizard/">Overpass Turbo query wizard</a> code (MIT Licensed)
|
---|
19 | * to build an Overpass QL from a {@link org.openstreetmap.josm.actions.search.SearchAction} like query.
|
---|
20 | *
|
---|
21 | * Requires a JavaScript {@link ScriptEngine}.
|
---|
22 | * @since 8744
|
---|
23 | */
|
---|
24 | public final class OverpassTurboQueryWizard {
|
---|
25 |
|
---|
26 | private static OverpassTurboQueryWizard instance;
|
---|
27 | private final ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
|
---|
28 |
|
---|
29 | /**
|
---|
30 | * Replies the unique instance of this class.
|
---|
31 | *
|
---|
32 | * @return the unique instance of this class
|
---|
33 | */
|
---|
34 | public static synchronized OverpassTurboQueryWizard getInstance() {
|
---|
35 | if (instance == null) {
|
---|
36 | instance = new OverpassTurboQueryWizard();
|
---|
37 | }
|
---|
38 | return instance;
|
---|
39 | }
|
---|
40 |
|
---|
41 | private OverpassTurboQueryWizard() {
|
---|
42 | try (final Reader reader = new InputStreamReader(
|
---|
43 | getClass().getResourceAsStream("/data/overpass-wizard.js"), StandardCharsets.UTF_8)) {
|
---|
44 | engine.eval("var console = {error: " + Main.class.getCanonicalName() + ".warn};");
|
---|
45 | engine.eval("var global = {};");
|
---|
46 | engine.eval(reader);
|
---|
47 | } catch (ScriptException | IOException ex) {
|
---|
48 | throw new RuntimeException("Failed to initialize OverpassTurboQueryWizard", ex);
|
---|
49 | }
|
---|
50 | }
|
---|
51 |
|
---|
52 | /**
|
---|
53 | * Builds an Overpass QL from a {@link org.openstreetmap.josm.actions.search.SearchAction} like query.
|
---|
54 | * @param search the {@link org.openstreetmap.josm.actions.search.SearchAction} like query
|
---|
55 | * @return an Overpass QL query
|
---|
56 | * @throws UncheckedParseException when the parsing fails
|
---|
57 | */
|
---|
58 | public String constructQuery(String search) throws UncheckedParseException {
|
---|
59 | try {
|
---|
60 | final Object result = ((Invocable) engine).invokeMethod(engine.get("global"),
|
---|
61 | "overpassWizard", search, new HashMap<String, Object>() { {
|
---|
62 | put("comment", false);
|
---|
63 | put("outputFormat", "xml");
|
---|
64 | put("outputMode", "recursive_meta");
|
---|
65 | } }
|
---|
66 | );
|
---|
67 | if (result == Boolean.FALSE) {
|
---|
68 | throw new UncheckedParseException();
|
---|
69 | }
|
---|
70 | String query = (String) result;
|
---|
71 | query = query.replace("[bbox:{{bbox}}]", "");
|
---|
72 | return query;
|
---|
73 | } catch (NoSuchMethodException e) {
|
---|
74 | throw new IllegalStateException();
|
---|
75 | } catch (ScriptException e) {
|
---|
76 | throw new RuntimeException("Failed to execute OverpassTurboQueryWizard", e);
|
---|
77 | }
|
---|
78 | }
|
---|
79 |
|
---|
80 | }
|
---|