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