source: josm/trunk/scripts/sync_editor-imagery-index.groovy @ 7726

Last change on this file since 7726 was 7726, checked in by bastiK, 9 years ago

see #10760 - add tool to compare both imagery lists

File size: 9.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2/**
3 * Compare and analyse the differences of the editor imagery index and the JOSM imagery list.
4 * The goal is to keep both lists in sync.
5 *
6 * The editor imagery index project (https://github.com/osmlab/editor-imagery-index)
7 * provides also a version in the JOSM format, but the JSON is the original source
8 * format, so we read that.
9 *
10 * How to run:
11 * -----------
12 *
13 * Main JOSM binary needs to be in classpath, e.g.
14 *
15 * $ groovy -cp ../dist/josm-custom.jar sync_editor-imagery-index.groovy
16 *
17 * Add option "-h" to show the available command line flags.
18 */
19import java.io.FileReader
20import java.util.List
21
22import javax.json.Json
23import javax.json.JsonArray
24import javax.json.JsonObject
25import javax.json.JsonReader
26
27import org.openstreetmap.josm.io.imagery.ImageryReader
28import org.openstreetmap.josm.data.imagery.ImageryInfo
29import org.openstreetmap.josm.tools.Utils
30
31class sync_editor_imagery_index {
32
33    List<ImageryInfo> josmEntries;
34    JsonArray eiiEntries;
35   
36    final static def EII_KNOWN_DUPLICATES = ["http://geolittoral.application.equipement.gouv.fr/wms/metropole?FORMAT=image/jpeg&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&Layers=ortholittorale&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}"]
37    final static def JOSM_KNOWN_DUPLICATES = ["http://geolittoral.application.equipement.gouv.fr/wms/metropole?FORMAT=image/jpeg&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&Layers=ortholittorale&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}"]
38
39    def eiiUrls = new HashMap<String, JsonObject>()
40    def josmUrls = new HashMap<String, ImageryInfo>()
41   
42    static String eiiInputFile = 'imagery.json'
43    static String josmInputFile = 'maps.xml'
44   
45    static def options
46   
47    /**
48     * Main method.
49     */
50    static main(def args) {
51        parse_command_line_arguments(args)
52        def script = new sync_editor_imagery_index()
53        script.loadJosmEntries()
54        println "*** Loaded ${script.josmEntries.size()} entries (JOSM). ***"
55        script.loadEIIEntries()
56        println "*** Loaded ${script.eiiEntries.size()} entries (EII). ***"
57        script.checkInOneButNotTheOther()
58        script.checkCommonEntries()
59    }
60   
61    /**
62     * Parse command line arguments.
63     */
64    static void parse_command_line_arguments(args) {
65        def cli = new CliBuilder()
66        cli._(longOpt:'eii_input', args:1, argName:"eii_input", "Input file for the editor imagery index (json). Default is $eiiInputFile (current directory).")
67        cli._(longOpt:'josm_input', args:1, argName:"josm_input", "Input file for the JOSM imagery list (xml). Default is $josmInputFile (current directory).")
68        cli.s(longOpt:'shorten', "shorten the output, so it is easier to read in a console window")
69        cli.h(longOpt:'help', "show this help")
70        options = cli.parse(args)
71
72        if (options.h) {
73            cli.usage()
74            System.exit(0)
75        }
76        if (options.eii_input) {
77            eiiInputFile = options.eii_input
78        }
79        if (options.josm_input) {
80            josmInputFile = options.josm_input
81        }
82    }
83
84    void loadEIIEntries() {
85        FileReader fr = new FileReader(eiiInputFile)
86        JsonReader jr = Json.createReader(fr)
87        eiiEntries = jr.readArray()
88        jr.close()
89       
90        for (def e : eiiEntries) {
91            def url = getUrl(e)
92            if (eiiUrls.containsKey(url) && !EII_KNOWN_DUPLICATES.contains(url))
93                throw new Exception("URL is not unique: "+url)
94            eiiUrls.put(url, e)
95        }
96    }
97
98    void loadJosmEntries() {
99        def reader = new ImageryReader(josmInputFile)
100        josmEntries = reader.parse()
101       
102        for (def e : josmEntries) {
103            def url = getUrl(e)
104            if (josmUrls.containsKey(url) && !JOSM_KNOWN_DUPLICATES.contains(url)) {
105                throw new Exception("URL is not unique: "+url)
106            }
107            josmUrls.put(url, e)
108        }
109    }
110
111    List inOneButNotTheOther(Map m1, Map m2) {
112        def l = []
113        for (def url : m1.keySet()) {
114            if (!m2.containsKey(url)) {
115                def name = getName(m1.get(url))
116                l += "  "+getDescription(m1.get(url))
117            }
118        }
119        l.sort()
120    }
121   
122    void checkInOneButNotTheOther() {
123        def l1 = inOneButNotTheOther(eiiUrls, josmUrls)
124        println "*** URLs found in EII but not in JOSM (${l1.size()}): ***"
125        if (l1.isEmpty()) {
126            println "  -"
127        } else {
128            println Utils.join("\n", l1)
129        }
130
131        def l2 = inOneButNotTheOther(josmUrls, eiiUrls)
132        println "*** URLs found in JOSM but not in EII (${l2.size()}): ***"
133        if (l2.isEmpty()) {
134            println "  -"
135        } else {
136            println Utils.join("\n", l2)
137        }
138    }
139   
140    void checkCommonEntries() {
141        println "*** Same URL, but different name: ***"
142        for (def url : eiiUrls.keySet()) {
143            def e = eiiUrls.get(url)
144            if (!josmUrls.containsKey(url)) continue
145            def j = josmUrls.get(url)
146            if (!getName(e).equals(getName(j))) {
147                println "  name differs: $url"
148                println "     (IEE):     ${getName(e)}"
149                println "     (JOSM):    ${getName(j)}"
150            }
151        }
152       
153        println "*** Same URL, but different type: ***"
154        for (def url : eiiUrls.keySet()) {
155            def e = eiiUrls.get(url)
156            if (!josmUrls.containsKey(url)) continue
157            def j = josmUrls.get(url)
158            if (!getType(e).equals(getType(j))) {
159                println "  type differs: ${getName(j)} - $url"
160                println "     (IEE):     ${getType(e)}"
161                println "     (JOSM):    ${getType(j)}"
162            }
163        }
164       
165        println "*** Same URL, but different zoom bounds: ***"
166        for (def url : eiiUrls.keySet()) {
167            def e = eiiUrls.get(url)
168            if (!josmUrls.containsKey(url)) continue
169            def j = josmUrls.get(url)
170
171            Integer eMinZoom = getMinZoom(e)
172            Integer jMinZoom = getMinZoom(j)
173            if (eMinZoom != jMinZoom) {
174                println "  minzoom differs: ${getDescription(j)}"
175                println "     (IEE):     ${eMinZoom}"
176                println "     (JOSM):    ${jMinZoom}"
177            }
178            Integer eMaxZoom = getMaxZoom(e)
179            Integer jMaxZoom = getMaxZoom(j)
180            if (eMaxZoom != jMaxZoom) {
181                println "  maxzoom differs: ${getDescription(j)}"
182                println "     (IEE):     ${eMaxZoom}"
183                println "     (JOSM):    ${jMaxZoom}"
184            }
185        }
186       
187        println "*** Same URL, but different country code: ***"
188        for (def url : eiiUrls.keySet()) {
189            def e = eiiUrls.get(url)
190            if (!josmUrls.containsKey(url)) continue
191            def j = josmUrls.get(url)
192            if (!getCountryCode(e).equals(getCountryCode(j))) {
193                println "  country code differs: ${getDescription(j)}"
194                println "     (IEE):     ${getCountryCode(e)}"
195                println "     (JOSM):    ${getCountryCode(j)}"
196            }
197        }
198    }
199   
200    /**
201     * Utility functions that allow uniform access for both ImageryInfo and JsonObject.
202     */
203    static String getUrl(Object e) {
204        if (e instanceof ImageryInfo) return e.url
205        return e.getString("url")
206    }
207    static String getName(Object e) {
208        if (e instanceof ImageryInfo) return e.name
209        return e.getString("name")
210    }
211    static String getType(Object e) {
212        if (e instanceof ImageryInfo) return e.getImageryType().getTypeString()
213        return e.getString("type")
214    }
215    static Integer getMinZoom(Object e) {
216        if (e instanceof ImageryInfo) {
217            int mz = e.getMinZoom()
218            return mz == 0 ? null : mz
219        } else {
220            def ext = e.getJsonObject("extent")
221            if (ext == null) return null
222            def num = ext.getJsonNumber("min_zoom")
223            if (num == null) return null
224            return num.intValue()
225        }
226    }
227    static Integer getMaxZoom(Object e) {
228        if (e instanceof ImageryInfo) {
229            int mz = e.getMaxZoom()
230            return mz == 0 ? null : mz
231        } else {
232            def ext = e.getJsonObject("extent")
233            if (ext == null) return null
234            def num = ext.getJsonNumber("max_zoom")
235            if (num == null) return null
236            return num.intValue()
237        }
238    }
239    static String getCountryCode(Object e) {
240        if (e instanceof ImageryInfo) return "".equals(e.getCountryCode()) ? null : e.getCountryCode()
241        return e.getString("country_code", null)
242    }
243    String getDescription(Object o) {
244        def url = getUrl(o)
245        def cc = getCountryCode(o)
246        if (cc == null) {
247            def j = josmUrls.get(url)
248            if (j != null) cc = getCountryCode(j)
249            if (cc == null) {
250                def e = eiiUrls.get(url)
251                if (e != null) cc = getCountryCode(e)
252            }
253        }
254        if (cc == null) {
255            cc = ''
256        } else {
257            cc = "[$cc] "
258        }
259        def d = cc + getName(o) + " - " + getUrl(o)
260        if (options.shorten) {
261            def MAXLEN = 140
262            if (d.length() > MAXLEN) d = d.substring(0, MAXLEN-1) + "..."
263        }
264        return d
265    }
266
267}
Note: See TracBrowser for help on using the repository browser.