source: josm/src/org/openstreetmap/josm/io/IncompleteDownloader.java@ 298

Last change on this file since 298 was 298, checked in by imi, 17 years ago
  • added license description to head of each source file
File size: 5.5 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.BufferedReader;
7import java.io.ByteArrayInputStream;
8import java.io.FileNotFoundException;
9import java.io.IOException;
10import java.io.InputStreamReader;
11import java.io.StringReader;
12import java.util.Collection;
13import java.util.ArrayList;
14
15import org.openstreetmap.josm.Main;
16import org.openstreetmap.josm.data.osm.DataSet;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.Segment;
19import org.openstreetmap.josm.data.osm.Way;
20import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
21import org.xml.sax.Attributes;
22import org.xml.sax.SAXException;
23
24import javax.swing.JOptionPane;
25import org.openstreetmap.josm.command.ChangeCommand;
26import org.openstreetmap.josm.command.Command;
27import org.openstreetmap.josm.command.SequenceCommand;
28
29import uk.co.wilson.xml.MinML2;
30
31/**
32 * Capable of downloading ways without having to fully parse their segments.
33 *
34 * @author Imi
35 */
36public class IncompleteDownloader extends OsmServerReader {
37
38 /**
39 * The new downloaded data will be inserted here.
40 */
41 public final DataSet data = new DataSet();
42
43 /**
44 * The list of incomplete Ways to download. The ways will be filled and are complete after download.
45 */
46 private final Collection<Way> toDownload;
47 private MergeVisitor merger = new MergeVisitor(data, null);
48
49 public IncompleteDownloader(Collection<Way> toDownload) {
50 this.toDownload = toDownload;
51 }
52
53 public void parse() throws SAXException, IOException {
54 Main.pleaseWaitDlg.currentAction.setText(tr("Downloading incomplete ways..."));
55 Main.pleaseWaitDlg.progress.setMaximum(toDownload.size());
56 Main.pleaseWaitDlg.progress.setValue(0);
57 ArrayList<Command> cmds = new ArrayList<Command>();
58 int i = 0;
59 try {
60 for (Way w : toDownload) {
61 // if some of the way's segments fail to download and the user
62 // decides to delete them, the download method will return an
63 // "edit way" command.
64 Command cmd = download(w);
65 if (cmd != null)
66 cmds.add(cmd);
67 Main.pleaseWaitDlg.progress.setValue(++i);
68 }
69 } catch (IOException e) {
70 if (!cancel)
71 throw e;
72 } catch (SAXException e) {
73 throw e;
74 } catch (Exception e) {
75 if (!cancel)
76 throw (e instanceof RuntimeException) ? (RuntimeException)e : new RuntimeException(e);
77 }
78 if (cmds.size() > 0)
79 Main.main.editLayer().add(new SequenceCommand(tr("Fix data errors"), cmds));
80 }
81
82 private static class SegmentParser extends MinML2 {
83 public long from, to;
84 @Override public void startElement(String ns, String lname, String qname, Attributes a) {
85 if (qname.equals("segment")) {
86 from = Long.parseLong(a.getValue("from"));
87 to = Long.parseLong(a.getValue("to"));
88 }
89 }
90 }
91
92 /**
93 * Downloads all missing segments from the given way. If segments fail do download,
94 * offers the user a chance to delete those segments from the way.
95 *
96 * @param w way to complete
97 * @return an "edit way" command if the user decided to delete segments
98 * @throws IOException
99 * @throws SAXException
100 */
101 private Command download(Way w) throws IOException, SAXException {
102 // get all the segments
103 Way newway = null;
104 for (Segment s : w.segments) {
105 if (!s.incomplete)
106 continue;
107 BufferedReader segReader;
108 try {
109 segReader = new BufferedReader(new InputStreamReader(getInputStream("segment/"+s.id, null), "UTF-8"));
110 } catch (FileNotFoundException e) {
111 Object[] options = {"Delete", "Ignore", "Abort"};
112 int n = JOptionPane.showOptionDialog(Main.parent,
113 tr("Segment {0} is deleted but part of Way {1}",s.id, w.id),
114 tr("Data error"),
115 JOptionPane.YES_NO_CANCEL_OPTION,
116 JOptionPane.ERROR_MESSAGE,
117 null, options, options[2]);
118 if (n == 0)
119 {
120 if( newway == null )
121 newway = new Way(w);
122 newway.segments.remove(s);
123 }
124 else if (n == 2)
125 {
126 e.printStackTrace();
127 throw new IOException(tr("Data error: Segment {0} is deleted but part of Way {1}", s.id, w.id));
128 }
129 continue;
130 }
131 StringBuilder segBuilder = new StringBuilder();
132 for (String line = segReader.readLine(); line != null; line = segReader.readLine())
133 segBuilder.append(line+"\n");
134 SegmentParser segmentParser = new SegmentParser();
135 segmentParser.parse(new StringReader(segBuilder.toString()));
136 if (segmentParser.from == 0 || segmentParser.to == 0)
137 throw new SAXException("Invalid segment response.");
138 if (!hasNode(segmentParser.from))
139 readNode(segmentParser.from, s.id).visit(merger);
140 if (!hasNode(segmentParser.to))
141 readNode(segmentParser.to, s.id).visit(merger);
142 readSegment(segBuilder.toString()).visit(merger);
143 }
144 if( newway != null )
145 return new ChangeCommand(w, newway);
146 return null;
147 }
148
149 private boolean hasNode(long id) {
150 for (Node n : Main.ds.nodes)
151 if (n.id == id)
152 return true;
153 return false;
154 }
155
156 private Segment readSegment(String seg) throws SAXException, IOException {
157 return OsmReader.parseDataSet(new ByteArrayInputStream(seg.getBytes("UTF-8")), data, null).segments.iterator().next();
158 }
159
160 private Node readNode(long id, long segId) throws SAXException, IOException {
161 try {
162 return OsmReader.parseDataSet(getInputStream("node/"+id, null), data, null).nodes.iterator().next();
163 } catch (FileNotFoundException e) {
164 e.printStackTrace();
165 throw new IOException(tr("Data error: Node {0} is deleted but part of Segment {1}", id, segId));
166 }
167 }
168}
Note: See TracBrowser for help on using the repository browser.