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

Last change on this file since 265 was 224, checked in by framm, 18 years ago

Fixed MergeVisitor so that it will never merge between objects that are
part of the group of objects being added - only between pre-existing
objects and those being added.

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