Ignore:
Timestamp:
2006-05-03T22:21:02+02:00 (20 years ago)
Author:
imi
Message:
  • added zoom/move around with Ctrl+direction keys / Ctrl +, Ctrl -
  • added progress bar counter of downloaded bytes
  • added support for little-osm (relaxed assumptions about osm/xml input format)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/org/openstreetmap/josm/io/OsmReader.java

    r91 r101  
    66import java.text.ParseException;
    77import java.text.SimpleDateFormat;
     8import java.util.Collection;
    89import java.util.HashMap;
     10import java.util.LinkedList;
    911import java.util.Map;
     12import java.util.Map.Entry;
     13
     14import javax.swing.BoundedRangeModel;
     15import javax.swing.JLabel;
    1016
    1117import org.openstreetmap.josm.data.coor.LatLon;
     
    1622import org.openstreetmap.josm.data.osm.Way;
    1723import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
     24import org.openstreetmap.josm.data.osm.visitor.Visitor;
    1825import org.xml.sax.Attributes;
    1926import org.xml.sax.SAXException;
     
    2431 * Parser for the Osm Api. Read from an input stream and construct a dataset out of it.
    2532 *
     33 * Reading process takes place in three phases. During the first phase (including xml parse),
     34 * all nodes are read and stored. Other information than nodes are stored in a raw list
     35 *
     36 * The second phase reads from the raw list all segments and create Segment objects.
     37 *
     38 * The third phase read all ways out of the remaining objects in the raw list.
     39 *
    2640 * @author Imi
    2741 */
    28 public class OsmReader extends MinML2 {
     42public class OsmReader {
    2943
    3044        /**
     
    3751         */
    3852        private AddVisitor adder = new AddVisitor(ds);
     53
     54        /**
     55         * All read nodes after phase 1.
     56         */
     57        private Map<Long, Node> nodes = new HashMap<Long, Node>();
    3958       
    40         /**
    41          * The current processed primitive.
    42          */
    43         private OsmPrimitive current;
    44 
    45         /**
    46          * All read nodes so far.
    47          */
    48         private Map<Long, Node> nodes = new HashMap<Long, Node>();
    49         /**
    50          * All read segents so far.
    51          */
    52         private Map<Long, Segment> segments = new HashMap<Long, Segment>();
     59        private static class OsmPrimitiveData extends OsmPrimitive {
     60                @Override public void visit(Visitor visitor) {}
     61                public int compareTo(OsmPrimitive o) {return 0;}
     62
     63                public void copyTo(OsmPrimitive osm) {
     64                        osm.id = id;
     65                        osm.keys = keys;
     66                        osm.modified = modified;
     67                        osm.selected = selected;
     68                        osm.deleted = deleted;
     69                        osm.timestamp = timestamp;
     70        }
     71        }
    5372       
    5473        /**
    55          * Parse the given input source and return the dataset.
    56          */
    57         public static DataSet parseDataSet(Reader source) throws SAXException, IOException {
    58                 OsmReader osm = new OsmReader(source);
    59 
    60                 // clear all negative ids (new to this file)
    61                 for (OsmPrimitive o : osm.ds.allPrimitives())
    62                         if (o.id < 0)
    63                                 o.id = 0;
    64                
    65                 return osm.ds;
    66         }
    67 
    68         private OsmReader(Reader source) throws SAXException, IOException {
    69                 parse(source);
    70         }
    71 
    72         @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    73                 try {
    74                         if (qName.equals("osm")) {
    75                                 if (atts == null)
    76                                         throw new SAXException("Unknown version.");
    77                                 if (!"0.3".equals(atts.getValue("version")))
    78                                         throw new SAXException("Unknown version "+atts.getValue("version"));
    79                         } else if (qName.equals("node")) {
    80                                 Node n = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
    81                                 current = n;
    82                                 readCommon(atts);
    83                                 current.id = getLong(atts, "id");
    84                                 nodes.put(n.id, n);
    85                         } else if (qName.equals("segment")) {
    86                                 Node from = nodes.get(getLong(atts, "from"));
    87                                 Node to = nodes.get(getLong(atts, "to"));
    88                                 if (from == null || to == null)
    89                                         throw new SAXException("Segment "+atts.getValue("id")+" is missing its nodes.");
    90                                 current = new Segment(from, to);
    91                                 readCommon(atts);
    92                                 segments.put(current.id, (Segment)current);
    93                         } else if (qName.equals("way")) {
    94                                 current = new Way();
    95                                 readCommon(atts);
    96                         } else if (qName.equals("seg")) {
    97                                 if (current instanceof Way) {
     74         * Data structure for the remaining segment objects
     75         * Maps the raw attributes to key/value pairs.
     76         */
     77        private Map<OsmPrimitiveData, long[]> segs = new HashMap<OsmPrimitiveData, long[]>();
     78        /**
     79         * Data structure for the remaining way objects
     80         */
     81        private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>();
     82
     83
     84        private class Parser extends MinML2 {
     85                /**
     86                 * The current osm primitive to be read.
     87                 */
     88                private OsmPrimitive current;
     89
     90                @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
     91                        try {
     92                                if (qName.equals("osm")) {
     93                                        if (atts == null)
     94                                                throw new SAXException("Unknown version.");
     95                                        if (!"0.3".equals(atts.getValue("version")))
     96                                                throw new SAXException("Unknown version "+atts.getValue("version"));
     97                                } else if (qName.equals("node")) {
     98                                        current = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
     99                                        readCommon(atts, current);
     100                                        nodes.put(current.id, (Node)current);
     101                                } else if (qName.equals("segment")) {
     102                                        current = new OsmPrimitiveData();
     103                                        readCommon(atts, current);
     104                                        segs.put((OsmPrimitiveData)current, new long[]{getLong(atts, "from"), getLong(atts, "to")});
     105                                } else if (qName.equals("way")) {
     106                                        current = new OsmPrimitiveData();
     107                                        readCommon(atts, current);
     108                                        ways.put((OsmPrimitiveData)current, new LinkedList<Long>());
     109                                } else if (qName.equals("seg")) {
     110                                        Collection<Long> list = ways.get(current);
     111                                        if (list == null)
     112                                                throw new SAXException("Found <seg> tag on non-way.");
    98113                                        long id = getLong(atts, "id");
    99114                                        if (id == 0)
    100115                                                throw new SAXException("Incomplete segment with id=0");
    101                                         Segment ls = segments.get(id);
    102                                         if (ls == null) {
    103                                                 ls = new Segment(id); // incomplete segment
    104                                                 segments.put(id, ls);
    105                                                 adder.visit(ls);
    106                                         }
    107                                         ((Way)current).segments.add(ls);
    108                                 }
    109                         } else if (qName.equals("tag"))
    110                                 current.put(atts.getValue("k"), atts.getValue("v"));
    111                 } catch (NumberFormatException x) {
    112             x.printStackTrace(); // SAXException does not chain correctly
    113                         throw new SAXException(x.getMessage(), x);
    114                 } catch (NullPointerException x) {
    115                         x.printStackTrace(); // SAXException does not chain correctly
    116                         throw new SAXException("NullPointerException. Possible some missing tags.", x);
    117                 }
    118         }
    119 
    120        
    121         @Override public void endElement(String namespaceURI, String localName, String qName) {
    122                 if (qName.equals("node") || qName.equals("segment") || qName.equals("way") || qName.equals("area")) {
    123                         current.visit(adder);
     116                                        list.add(id);
     117                                } else if (qName.equals("tag"))
     118                                        current.put(atts.getValue("k"), atts.getValue("v"));
     119                        } catch (NumberFormatException x) {
     120                                x.printStackTrace(); // SAXException does not chain correctly
     121                                throw new SAXException(x.getMessage(), x);
     122                        } catch (NullPointerException x) {
     123                                x.printStackTrace(); // SAXException does not chain correctly
     124                                throw new SAXException("NullPointerException. Possible some missing tags.", x);
     125                        }
     126                }
     127
     128                private double getDouble(Attributes atts, String value) {
     129                        return Double.parseDouble(atts.getValue(value));
    124130                }
    125131        }
     
    128134         * Read out the common attributes from atts and put them into this.current.
    129135         */
    130         private void readCommon(Attributes atts) throws SAXException {
     136        void readCommon(Attributes atts, OsmPrimitive current) throws SAXException {
    131137                current.id = getLong(atts, "id");
    132138                if (current.id == 0)
    133139                        throw new SAXException("Illegal object with id=0");
    134                
     140
    135141                String time = atts.getValue("timestamp");
    136142                if (time != null && time.length() != 0) {
    137143                        try {
    138144                                DateFormat df = new SimpleDateFormat("y-M-d H:m:s");
    139                     current.timestamp = df.parse(time);
    140             } catch (ParseException e) {
    141                     e.printStackTrace();
    142                     throw new SAXException("Couldn't read time format '"+time+"'.");
    143             }
    144                 }
    145                
     145                                current.timestamp = df.parse(time);
     146                        } catch (ParseException e) {
     147                                e.printStackTrace();
     148                                throw new SAXException("Couldn't read time format '"+time+"'.");
     149                        }
     150                }
     151
    146152                String action = atts.getValue("action");
    147153                if (action == null)
     
    152158                        current.modified = true;
    153159        }
    154 
    155         private double getDouble(Attributes atts, String value) {
    156                 return Double.parseDouble(atts.getValue(value));
    157         }
    158         private long getLong(Attributes atts, String value) {
    159                 return Long.parseLong(atts.getValue(value));
     160        private long getLong(Attributes atts, String value) throws SAXException {
     161                String s = atts.getValue(value);
     162                if (s == null)
     163                        throw new SAXException("Missing required attirbute '"+value+"'");
     164                return Long.parseLong(s);
     165        }
     166
     167        private void createSegments() {
     168                for (Entry<OsmPrimitiveData, long[]> e : segs.entrySet()) {
     169                        Node from = nodes.get(e.getValue()[0]);
     170                        Node to = nodes.get(e.getValue()[1]);
     171                        if (from == null || to == null)
     172                                continue; //TODO: implement support for incomplete nodes.
     173                        Segment s = new Segment(from, to);
     174                        e.getKey().copyTo(s);
     175                        segments.put(s.id, s);
     176                        adder.visit(s);
     177                }
     178        }
     179
     180        private void createWays() {
     181                for (Entry<OsmPrimitiveData, Collection<Long>> e : ways.entrySet()) {
     182                        Way w = new Way();
     183                        for (long id : e.getValue()) {
     184                                Segment s = segments.get(id);
     185                                if (s == null)
     186                                        s = new Segment(id); // incomplete line segment
     187                                w.segments.add(s);
     188                        }
     189                        e.getKey().copyTo(w);
     190                        adder.visit(w);
     191                }
     192        }
     193
     194        /**
     195         * All read segments after phase 2.
     196         */
     197        private Map<Long, Segment> segments = new HashMap<Long, Segment>();
     198
     199        /**
     200         * Parse the given input source and return the dataset.
     201         */
     202        public static DataSet parseDataSet(Reader source, JLabel currentAction, BoundedRangeModel progress) throws SAXException, IOException {
     203                OsmReader osm = new OsmReader();
     204
     205                // phase 1: Parse nodes and read in raw segments and ways
     206                osm.new Parser().parse(source);
     207                if (progress != null)
     208                        progress.setValue(0);
     209                if (currentAction != null)
     210                        currentAction.setText("Preparing data...");
     211                for (Node n : osm.nodes.values())
     212                        osm.adder.visit(n);
     213
     214                try {
     215                        osm.createSegments();
     216                        osm.createWays();
     217                } catch (NumberFormatException e) {
     218                        e.printStackTrace();
     219                        throw new SAXException("Illformed Node id");
     220                }
     221
     222                // clear all negative ids (new to this file)
     223                for (OsmPrimitive o : osm.ds.allPrimitives())
     224                        if (o.id < 0)
     225                                o.id = 0;
     226
     227                return osm.ds;
    160228        }
    161229}
Note: See TracChangeset for help on using the changeset viewer.