source: osm/applications/editors/josm/haiti_earthquake/radiotv/UpdateFileBuilder.groovy@ 24143

Last change on this file since 24143 was 19939, checked in by guggis, 15 years ago

Scripts for importing radio/tv studios in Haiti

File size: 5.4 KB
Line 
1package ch.guggis.haiti.radiotv;
2
3import java.io.OutputStreamWriter;
4import java.io.StringReader;
5import java.io.BufferedReader;
6import javax.xml.xpath.*
7import groovy.util.IndentPrinter;
8import groovy.util.XmlParser
9import groovy.xml.MarkupBuilder;
10import groovy.xml.DOMBuilder;
11import javax.xml.parsers.DocumentBuilderFactory
12import org.xml.sax.InputSource
13import groovy.xml.StreamingMarkupBuilder
14import org.w3c.dom.Node
15import java.text.SimpleDateFormat
16import groovy.util.CliBuilder
17import groovy.xml.XmlUtil
18
19/**
20 * Takes a file with the newest data for studios from IMS and creates an OSM file
21 * with property ids, version info and action="modify" attributes, in order to open
22 * it in JOSM and upload it to OSM.
23 *
24 */
25class UpdateFileBuilder {
26 private static def xpath = XPathFactory.newInstance().newXPath()
27 def lastChangesetId
28 def reader
29 def writer
30
31 def queryApi(url) {
32 def builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
33 def doc = builder.parse(
34 new InputSource(
35 new InputStreamReader(
36 new URL(url).openStream(),
37 "UTF-8"
38 )
39 )
40 ).documentElement
41 return doc
42 }
43 /**
44 * Retrieves the nodes which have been updated and create in the last update of
45 * the studio dataset
46 *
47 */
48 def fetchChangeset() {
49 return queryApi("http://api.openstreetmap.org/api/0.6/changeset/${lastChangesetId}/download")
50 }
51
52
53 /**
54 * Fetch the current version for all nodes representing IMS studios
55 *
56 */
57 def currentIMSStudioObjectsFromOsm(changeset) {
58 def ids = []
59 xpath.evaluate("//node", changeset, XPathConstants.NODESET).each { node ->
60 ids << xpath.evaluate("./@id", node, XPathConstants.STRING)
61 }
62 return queryApi("http://api.openstreetmap.org/api/0.6/nodes?nodes=" + ids.join(","))
63 }
64
65 /**
66 * Load the new data from the OSM file
67 *
68 */
69 def loadNewStudios() {
70 def builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
71 def doc = builder.parse(
72 new InputSource(
73 reader
74 )
75 ).documentElement
76 return doc
77 }
78
79 /**
80 * Update the id and version in the studio objects.
81 */
82 def updateIdsAndVersions(newStudios, oldStudios) {
83 xpath.evaluate("//node", newStudios, XPathConstants.NODESET).each { newStudio ->
84 def imsid = xpath.evaluate("./tag[@k = 'ims:id']/@v", newStudio, XPathConstants.STRING)
85 println "Processing studio '${imsid}' ..."
86 def osmid = xpath.evaluate("//tag[@k = 'ims:id'][@v = '${imsid}']/../@id", oldStudios, XPathConstants.STRING)
87 def osmversion = xpath.evaluate("//tag[@k = 'pid'][@v = '${imsid}']/../@version", oldStudios, XPathConstants.STRING)
88 if (!osmid) {
89 println "Warning: didn't find an existing node for studio '${imsid}'. Adding the studio instead of updating it."
90 return
91 }
92 newStudio.setAttribute("id", osmid)
93 newStudio.setAttribute("version", osmversion)
94 newStudio.setAttribute("action", "modify")
95 }
96 return newStudios
97 }
98
99
100 def process() {
101 println "Fetching changeset '${lastChangesetId}' from OSM API ..."
102 def changeset = fetchChangeset()
103 println "Fetching the current versions of the nodes from the OSM API ..."
104 def oldStudios = currentIMSStudioObjectsFromOsm(changeset)
105 println "Loading the new nodes for IMS studios ..."
106 def newStudios = loadNewStudios()
107 println "Updating the ids and versions of the new studios ..."
108 updateIdsAndVersions(newStudios, oldStudios)
109 println "Writing the update changeset file ..."
110 writer.println newStudios
111 writer.flush()
112 }
113
114 def usage() {
115 println """
116groovy ch.guggis.haiti.radiotv.UpdateFileBuilder [options]
117Options:
118 -cs, --last-changeset the changeset id used in the last upload. Mandatory.
119 -h, --help show help information
120 -i, --input-file the input file. Reads from stdin if missing
121 -o, --output-file the output file. Writes to stdout if missing.
122"""
123 }
124
125 def fail(msg) {
126 println msg
127 usage()
128 System.exit(1)
129 }
130
131 def processCommandLineOptions(argArray) {
132 def inputFile
133 def outputFile
134 def args = Arrays.asList(argArray)
135 args = args.reverse()
136 def arg = args.pop()
137 while(arg != null) {
138 switch(arg) {
139 case "-i":
140 case "--input-file":
141 inputFile = args.pop()
142 if (inputFile == null) {
143 fail "Error: missing input file"
144 }
145 break
146 case "-o":
147 case "--output-file":
148 outputFile = args.pop()
149 if (outputFile == null) {
150 fail "Error: missing output file"
151 }
152 break
153 case "-cs":
154 case "--last-changeset":
155 lastChangesetId = args.pop()
156 if (lastChangesetId == null) {
157 fail "Error: missing changeset id"
158 }
159 break
160
161 case "-h":
162 case "--help":
163 usage()
164 System.exit(0)
165 break
166
167 default:
168 fail "Illegal argument ${arg}"
169 }
170 arg = args.empty ? null : args.pop()
171 }
172
173 if (!lastChangesetId) {
174 fail("Mandatory command line option '-cs' missing.")
175 System.exit(1)
176 }
177
178 if (inputFile) {
179 reader = new File(inputFile).newReader("UTF-8")
180 } else {
181 reader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"))
182 }
183 if (outputFile) {
184 writer = new File(outputFile).newWriter("UTF-8")
185 } else {
186 writer = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"))
187 }
188 }
189
190 static public void main(args) {
191 def task = new UpdateFileBuilder()
192 task.processCommandLineOptions(args)
193 task.process()
194 }
195}
Note: See TracBrowser for help on using the repository browser.