source: osm/applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/CadastreInterface.java@ 18743

Last change on this file since 18743 was 18544, checked in by pieren, 16 years ago

Add licence in headers for GPL compliance.

  • Property svn:eol-style set to native
File size: 22.8 KB
Line 
1// License: GPL. v2 and later. Copyright 2008-2009 by Pieren <pieren3@gmail.com> and others
2package cadastre_fr;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagLayout;
7import java.io.BufferedReader;
8import java.io.IOException;
9import java.io.InputStreamReader;
10import java.io.OutputStream;
11import java.net.HttpURLConnection;
12import java.net.MalformedURLException;
13import java.net.URL;
14import java.util.Vector;
15
16import javax.swing.JComboBox;
17import javax.swing.JDialog;
18import javax.swing.JOptionPane;
19import javax.swing.JPanel;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.data.coor.EastNorth;
23import org.openstreetmap.josm.gui.layer.Layer;
24import org.openstreetmap.josm.tools.GBC;
25
26public class CadastreInterface {
27 public boolean downloadCancelled = false;
28 public HttpURLConnection urlConn = null;
29
30 private String cookie;
31 private String interfaceRef = null;
32 private String lastWMSLayerName = null;
33 private URL searchFormURL;
34 private Vector<String> listOfCommunes = new Vector<String>();
35 private Vector<String> listOfTA = new Vector<String>();
36 class PlanImage {
37 String name;
38 String ref;
39 PlanImage(String name, String ref) {
40 this.name = name;
41 this.ref = ref;
42 }
43 }
44 private Vector<PlanImage> listOfFeuilles = new Vector<PlanImage>();
45
46 final String baseURL = "http://www.cadastre.gouv.fr";
47 final String cImageFormat = "Cette commune est au format ";
48 final String cCommuneListStart = "<select name=\"codeCommune\"";
49 final String cCommuneListEnd = "</select>";
50 final String c0ptionListStart = "<option value=\"";
51 final String cOptionListEnd = "</option>";
52 final String cBBoxCommunStart = "new GeoBox(";
53 final String cBBoxCommunEnd = ")";
54
55 final String cInterfaceVector = "afficherCarteCommune.do";
56 final String cInterfaceRasterTA = "afficherCarteTa.do";
57 final String cInterfaceRasterFeuille = "afficherCarteFeuille.do";
58 final String cImageLinkStart = "title=\"image\"><a href=\"#\" onClick=\"popup('afficherCarteFeuille.do?f=";
59 final String cImageNameStart = ">Feuille ";
60
61 public boolean retrieveInterface(WMSLayer wmsLayer) throws DuplicateLayerException {
62 if (wmsLayer.getName().equals(""))
63 return false;
64 // open the session with the French Cadastre web front end
65 downloadCancelled = false;
66 try {
67 if (cookie == null || !wmsLayer.getName().equals(lastWMSLayerName)) {
68 getCookie();
69 getInterface(wmsLayer);
70 this.lastWMSLayerName = wmsLayer.getName();
71 }
72 openInterface();
73 } catch (IOException e) {
74 /*JOptionPane.showMessageDialog(Main.parent,
75 tr("Town/city {0} not found or not available\n" +
76 "or action canceled", wmsLayer.getLocation()));*/
77 JOptionPane pane = new JOptionPane(
78 tr("Town/city {0} not found or not available\n" +
79 "or action canceled", wmsLayer.getLocation()),
80 JOptionPane.INFORMATION_MESSAGE);
81 // this below is a temporary workaround to fix the "always on top" issue
82 JDialog dialog = pane.createDialog(Main.parent, tr("Select commune"));
83 CadastrePlugin.prepareDialog(dialog);
84 dialog.setVisible(true);
85 // till here
86 return false;
87 }
88 return true;
89 }
90
91 private void getCookie() throws IOException {
92 try {
93 // first, get the cookie from Cadastre to allow next downloads
94 searchFormURL = new URL(baseURL + "/scpc/rechercherPlan.do");
95 urlConn = (HttpURLConnection)searchFormURL.openConnection();
96 urlConn.setRequestMethod("GET");
97 urlConn.connect();
98 if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
99 throw new IOException("Cannot get Cadastre cookie.");
100 }
101 System.out.println("GET "+searchFormURL);
102 BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
103 while(in.readLine() != null) {} // read the buffer otherwise we sent POST too early
104 String headerName=null;
105 for (int i=1; (headerName = urlConn.getHeaderFieldKey(i))!=null; i++) {
106 if (headerName.equals("Set-Cookie")) {
107 cookie = urlConn.getHeaderField(i);
108 cookie = cookie.substring(0, cookie.indexOf(";"));
109 System.out.println("Cookie="+cookie);
110 }
111 }
112 } catch (MalformedURLException e) {
113 throw (IOException) new IOException(
114 "Illegal url.").initCause(e);
115 }
116 }
117
118 public void resetCookie() {
119 lastWMSLayerName = null;
120 }
121
122 public void resetCookieIfNewLayer(String newWMSLayerName) {
123 if (!newWMSLayerName.equals(lastWMSLayerName)) {
124 resetCookie();
125 }
126 }
127
128 public void setCookie() {
129 this.urlConn.setRequestProperty("Cookie", this.cookie);
130 }
131
132 public void setCookie(HttpURLConnection urlConn) {
133 urlConn.setRequestProperty("Cookie", this.cookie);
134 }
135
136 private void getInterface(WMSLayer wmsLayer) throws IOException, DuplicateLayerException {
137 // first attempt : search for given name without codeCommune
138 interfaceRef = postForm(wmsLayer, "");
139 // second attempt either from known codeCommune (e.g. from cache) or from ComboBox
140 if (interfaceRef == null) {
141 if (!wmsLayer.getCodeCommune().equals("")) {
142 // codeCommune is already known (from previous request or from cache on disk)
143 interfaceRef = postForm(wmsLayer, wmsLayer.getCodeCommune());
144 } else {
145 if (listOfCommunes.size() > 1) {
146 // commune unknown, prompt the list of communes from
147 // server and try with codeCommune
148 wmsLayer.setCodeCommune(selectCommuneDialog());
149 checkLayerDuplicates(wmsLayer);
150 interfaceRef = postForm(wmsLayer, wmsLayer.getCodeCommune());
151 }
152 if (listOfCommunes.size() == 1 && wmsLayer.isRaster()) {
153 // commune known but raster format. Select "Feuille" (non-georeferenced image) from list.
154 int res = selectFeuilleDialog();
155 if (res != -1) {
156 // TODO
157 wmsLayer.setCodeCommune(listOfFeuilles.elementAt(res).name);
158 checkLayerDuplicates(wmsLayer);
159 interfaceRef = buildRasterFeuilleInterfaceRef(wmsLayer.getCodeCommune());
160 }
161 }
162 }
163 }
164
165 if (interfaceRef == null)
166 throw new IOException("Town/city " + wmsLayer.getLocation() + " not found.");
167 }
168
169 private void openInterface() throws IOException {
170 try {
171 // finally, open the interface on server side giving access to the wms server
172 String lines = null;
173 String ln = null;
174 URL interfaceURL = new URL(baseURL + "/scpc/"+interfaceRef);
175 urlConn = (HttpURLConnection)interfaceURL.openConnection();
176 urlConn.setRequestMethod("GET");
177 setCookie();
178 urlConn.connect();
179 if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
180 throw new IOException("Cannot open Cadastre interface. GET response:"+urlConn.getResponseCode());
181 }
182 System.out.println("GET "+interfaceURL);
183 BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
184 //while(in.readLine() != null) {} // read the buffer otherwise we sent POST too early
185 while ((ln = in.readLine()) != null) {
186 lines += ln;
187 }
188 } catch (MalformedURLException e) {
189 throw (IOException) new IOException(
190 "CadastreGrabber: Illegal url.").initCause(e);
191 }
192 }
193
194 /**
195 * Post the form with the commune name and check the returned answer which is embedded
196 * in HTTP XML packets. This function doesn't use an XML parser yet but that would be a good idea
197 * for the next releases.
198 * Two possibilities :
199 * - either the commune name matches and we receive an URL starting with "afficherCarteCommune.do" or
200 * - we don't receive a single answer but a list of possible values. This answer looks like:
201 * <select name="codeCommune" class="long erreur" id="codeCommune">
202 * <option value="">Choisir</option>
203 * <option value="50061" >COLMARS - 04370</option>
204 * <option value="QK066" >COLMAR - 68000</option>
205 * </select>
206 * The returned string is the interface name used in further requests, e.g. "afficherCarteCommune.do?c=QP224"
207 * where QP224 is the code commune known by the WMS (or "afficherCarteTa.do?c=..." for raster images).
208 *
209 * @param location
210 * @param codeCommune
211 * @return retURL url to available code commune in the cadastre; "" if not found
212 * @throws IOException
213 */
214 private String postForm(WMSLayer wmsLayer, String codeCommune) throws IOException {
215 try {
216 String ln = null;
217 String lines = null;
218 listOfCommunes.clear();
219 listOfTA.clear();
220 // send a POST request with a city/town/village name
221 String content = "numerovoie=";
222 content += "&indiceRepetition=";
223 content += "&nomvoie=";
224 content += "&lieuDit=";
225 if (codeCommune == "") {
226 content += "&ville=" + new String(java.net.URLEncoder.encode(wmsLayer.getLocation(), "UTF-8"));
227 content += "&codePostal=";
228 } else {
229 content += "&codeCommune=" + codeCommune;
230 }
231 content += "&codeDepartement=";
232 content += "&nbResultatParPage=10";
233 urlConn = (HttpURLConnection)searchFormURL.openConnection();
234 urlConn.setRequestMethod("POST");
235 urlConn.setDoOutput(true);
236 urlConn.setDoInput(true);
237 setCookie();
238 OutputStream wr = urlConn.getOutputStream();
239 wr.write(content.getBytes());
240 System.out.println("POST "+content);
241 wr.flush();
242 wr.close();
243 BufferedReader rd = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
244 while ((ln = rd.readLine()) != null) {
245 lines += ln;
246 }
247 rd.close();
248 urlConn.disconnect();
249 if (lines != null) {
250 if (lines.indexOf(cImageFormat) != -1) {
251 int i = lines.indexOf(cImageFormat);
252 int j = lines.indexOf(".", i);
253 wmsLayer.setRaster(lines.substring(i+cImageFormat.length(), j).equals("image"));
254 }
255 if (!wmsLayer.isRaster() && lines.indexOf(cInterfaceVector) != -1) { // "afficherCarteCommune.do"
256 // shall be something like: interfaceRef = "afficherCarteCommune.do?c=X2269";
257 lines = lines.substring(lines.indexOf(cInterfaceVector),lines.length());
258 lines = lines.substring(0, lines.indexOf("'"));
259 System.out.println("interface ref.:"+lines);
260 return lines;
261 } else if (wmsLayer.isRaster() && lines.indexOf(cInterfaceRasterTA) != -1) { // "afficherCarteTa.do"
262 // list of values parsed in listOfFeuilles (list all non-georeferenced images)
263 lines = getFeuillesList();
264 if (!downloadCancelled) {
265 parseFeuillesList(lines);
266 if (listOfFeuilles.size() > 0) {
267 int res = selectFeuilleDialog();
268 if (res != -1) {
269 wmsLayer.setCodeCommune(listOfFeuilles.elementAt(res).name);
270 checkLayerDuplicates(wmsLayer);
271 interfaceRef = buildRasterFeuilleInterfaceRef(wmsLayer.getCodeCommune());
272 wmsLayer.setCodeCommune(listOfFeuilles.elementAt(res).ref);
273 lines = buildRasterFeuilleInterfaceRef(listOfFeuilles.elementAt(res).ref);
274 System.out.println("interface ref.:"+lines);
275 return lines;
276 }
277 }
278 }
279 return null;
280 } else if (lines.indexOf(cCommuneListStart) != -1 && lines.indexOf(cCommuneListEnd) != -1) {
281 // list of values parsed in listOfCommunes
282 int i = lines.indexOf(cCommuneListStart);
283 int j = lines.indexOf(cCommuneListEnd, i);
284 parseCommuneList(lines.substring(i, j));
285 }
286 }
287 } catch (MalformedURLException e) {
288 throw (IOException) new IOException(
289 "Illegal url.").initCause(e);
290 } catch (Exception e){
291 e.printStackTrace();
292 }
293 return null;
294 }
295
296 private void parseCommuneList(String input) {
297 if (input.indexOf(c0ptionListStart) != -1) {
298 while (input.indexOf("<option value=\"") != -1) {
299 int i = input.indexOf(c0ptionListStart);
300 int j = input.indexOf(cOptionListEnd, i+c0ptionListStart.length());
301 int k = input.indexOf("\"", i+c0ptionListStart.length());
302 if (j != -1 && k > (i + c0ptionListStart.length())) {
303 String lov = new String(input.substring(i+c0ptionListStart.length()-1, j));
304 if (lov.indexOf(">") != -1) {
305 System.out.println("parse "+lov);
306 listOfCommunes.add(lov);
307 } else
308 System.err.println("unable to parse commune string:"+lov);
309 }
310 input = input.substring(j+cOptionListEnd.length());
311 }
312 }
313 }
314
315 private String getFeuillesList() {
316 // get all images in one html page
317 String ln = null;
318 String lines = null;
319 HttpURLConnection urlConn2 = null;
320 try {
321 URL getAllImagesURL = new URL(baseURL + "/scpc/listerFeuillesParcommune.do?keepVolatileSession=&offset=2000");
322 urlConn2 = (HttpURLConnection)getAllImagesURL.openConnection();
323 setCookie(urlConn2);
324 urlConn2.connect();
325 System.out.println("GET "+getAllImagesURL);
326 BufferedReader rd = new BufferedReader(new InputStreamReader(urlConn2.getInputStream()));
327 while ((ln = rd.readLine()) != null) {
328 lines += ln;
329 }
330 rd.close();
331 urlConn2.disconnect();
332 //System.out.println("GET="+lines);
333 } catch (IOException e) {
334 listOfFeuilles.clear();
335 e.printStackTrace();
336 }
337 return lines;
338 }
339
340 private void parseFeuillesList(String input) {
341 listOfFeuilles.clear();
342 while (input.indexOf(cImageLinkStart) != -1) {
343 input = input.substring(input.indexOf(cImageLinkStart)+cImageLinkStart.length());
344 String refFeuille = input.substring(0, input.indexOf("'"));
345 String nameFeuille = input.substring(
346 input.indexOf(cImageNameStart)+cImageNameStart.length(),
347 input.indexOf(" -"));
348 listOfFeuilles.add(new PlanImage(nameFeuille, refFeuille));
349 }
350 }
351
352 private String selectCommuneDialog() {
353 JPanel p = new JPanel(new GridBagLayout());
354 String[] communeList = new String[listOfCommunes.size() + 1];
355 communeList[0] = tr("Choose from...");
356 for (int i = 0; i < listOfCommunes.size(); i++) {
357 communeList[i + 1] = listOfCommunes.elementAt(i).substring(listOfCommunes.elementAt(i).indexOf(">")+1);
358 }
359 JComboBox inputCommuneList = new JComboBox(communeList);
360 p.add(inputCommuneList, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 0, 0, 0));
361 JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null) {
362 private static final long serialVersionUID = 1L;
363 };
364 //pane.createDialog(Main.parent, tr("Select commune")).setVisible(true);
365 // this below is a temporary workaround to fix the "always on top" issue
366 JDialog dialog = pane.createDialog(Main.parent, tr("Select commune"));
367 CadastrePlugin.prepareDialog(dialog);
368 dialog.setVisible(true);
369 // till here
370 if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
371 return null;
372 String result = listOfCommunes.elementAt(inputCommuneList.getSelectedIndex()-1);
373 return result.substring(1, result.indexOf(">")-2);
374 }
375
376 private int selectFeuilleDialog() {
377 JPanel p = new JPanel(new GridBagLayout());
378 Vector<String> ImageNames = new Vector<String>();
379 for (PlanImage src : listOfFeuilles) {
380 ImageNames.add(src.name);
381 }
382 JComboBox inputFeuilleList = new JComboBox(ImageNames);
383 p.add(inputFeuilleList, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 0, 0, 0));
384 JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null);
385 //pane.createDialog(Main.parent, tr("Select Feuille")).setVisible(true);
386 // this below is a temporary workaround to fix the "always on top" issue
387 JDialog dialog = pane.createDialog(Main.parent, tr("Select Feuille"));
388 CadastrePlugin.prepareDialog(dialog);
389 dialog.setVisible(true);
390 // till here
391 if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
392 return -1;
393 int result = inputFeuilleList.getSelectedIndex();
394 return result;
395 }
396
397 private String buildRasterFeuilleInterfaceRef(String codeCommune) {
398 return cInterfaceRasterFeuille + "?f=" + codeCommune;
399 }
400
401 /**
402 * Retrieve the bounding box size in pixels of the whole commune (point 0,0 at top, left corner)
403 * and store it in given wmsLayer
404 * In case of raster image, we also check in the same http request if the image is already georeferenced
405 * and store the result in the wmsLayer as well.
406 * @param wmsLayer the WMSLayer where the commune data and images are stored
407 * @throws IOException
408 */
409 public void retrieveCommuneBBox(WMSLayer wmsLayer) throws IOException {
410 if (interfaceRef == null)
411 return;
412 String ln = null;
413 String line = null;
414 // send GET opening normally the small window with the commune overview
415 String content = baseURL + "/scpc/" + interfaceRef;
416 content += "&dontSaveLastForward&keepVolatileSession=";
417 searchFormURL = new URL(content);
418 urlConn = (HttpURLConnection)searchFormURL.openConnection();
419 urlConn.setRequestMethod("GET");
420 setCookie();
421 urlConn.connect();
422 if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
423 throw new IOException("Cannot get Cadastre response.");
424 }
425 System.out.println("GET "+searchFormURL);
426 BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
427 while ((ln = in.readLine()) != null) {
428 line += ln;
429 }
430 in.close();
431 urlConn.disconnect();
432 parseBBoxCommune(wmsLayer, line);
433 if (wmsLayer.isRaster() && !wmsLayer.isAlreadyGeoreferenced()) {
434 parseGeoreferences(wmsLayer, line);
435 }
436 }
437
438 private void parseBBoxCommune(WMSLayer wmsLayer, String input) {
439 if (input.indexOf(cBBoxCommunStart) != -1) {
440 input = input.substring(input.indexOf(cBBoxCommunStart));
441 int i = input.indexOf(",");
442 double minx = Double.parseDouble(input.substring(cBBoxCommunStart.length(), i));
443 int j = input.indexOf(",", i+1);
444 double miny = Double.parseDouble(input.substring(i+1, j));
445 int k = input.indexOf(",", j+1);
446 double maxx = Double.parseDouble(input.substring(j+1, k));
447 int l = input.indexOf(cBBoxCommunEnd, k+1);
448 double maxy = Double.parseDouble(input.substring(k+1, l));
449 wmsLayer.setCommuneBBox( new EastNorthBound(new EastNorth(minx,miny), new EastNorth(maxx,maxy)));
450 }
451 }
452
453 private void parseGeoreferences(WMSLayer wmsLayer, String input) {
454 if (input.lastIndexOf(cBBoxCommunStart) != -1) {
455 input = input.substring(input.lastIndexOf(cBBoxCommunStart));
456 input = input.substring(input.indexOf(cBBoxCommunEnd)+cBBoxCommunEnd.length());
457 int i = input.indexOf(",");
458 int j = input.indexOf(",", i+1);
459 double angle = Double.parseDouble(input.substring(i+1, j));
460 int k = input.indexOf(",", j+1);
461 double scale_origin = Double.parseDouble(input.substring(j+1, k));
462 int l = input.indexOf(",", k+1);
463 double dpi = Double.parseDouble(input.substring(k+1, l));
464 int m = input.indexOf(",", l+1);
465 double fX = Double.parseDouble(input.substring(l+1, m));
466 int n = input.indexOf(",", m+1);
467 double fY = Double.parseDouble(input.substring(m+1, n));
468 int o = input.indexOf(",", n+1);
469 double X0 = Double.parseDouble(input.substring(n+1, o));
470 int p = input.indexOf(",", o+1);
471 double Y0 = Double.parseDouble(input.substring(o+1, p));
472 if (X0 != 0.0 && Y0 != 0) {
473 wmsLayer.setAlreadyGeoreferenced(true);
474 wmsLayer.fX = fX;
475 wmsLayer.fY = fY;
476 wmsLayer.angle = angle;
477 wmsLayer.X0 = X0;
478 wmsLayer.Y0 = Y0;
479 }
480 System.out.println("parse georef:"+angle+","+scale_origin+","+dpi+","+fX+","+
481 fY+","+X0+","+Y0);
482 }
483 }
484
485 private void checkLayerDuplicates(WMSLayer wmsLayer) throws DuplicateLayerException {
486 if (Main.map != null) {
487 for (Layer l : Main.map.mapView.getAllLayers()) {
488 if (l instanceof WMSLayer && l.getName().equals(wmsLayer.getName()) && (l != wmsLayer)) {
489 System.out.println("Try to grab into a new layer when "+wmsLayer.getName()+" is already opened.");
490 // remove the duplicated layer
491 Main.map.mapView.removeLayer(wmsLayer);
492 throw new DuplicateLayerException();
493 }
494 }
495 }
496 }
497
498 public void cancel() {
499 if (urlConn != null) {
500 urlConn.setConnectTimeout(1);
501 urlConn.setReadTimeout(1);
502 //urlConn.disconnect();
503 }
504 downloadCancelled = true;
505 lastWMSLayerName = null;
506 }
507
508}
Note: See TracBrowser for help on using the repository browser.