Changeset 769 in josm


Ignore:
Timestamp:
2008-08-11T22:04:37+02:00 (11 years ago)
Author:
framm
Message:
  • add support for <bounds> tag in .osm files using four attributes minlat,maxlat,minlon,maxlon. old <bound> still supported for a transition period. fixes #1112.
Location:
trunk/src/org/openstreetmap/josm/io
Files:
3 edited

Legend:

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

    r627 r769  
    9898                Main.pleaseWaitDlg.currentAction.setText(tr("Downloading OSM data..."));
    9999                final DataSet data = OsmReader.parseDataSet(in, null, Main.pleaseWaitDlg);
     100            /*
     101             * We're not doing this here anymore as the API now properly sets a bounds element
     102             * which will get parsed.
    100103                String origin = Main.pref.get("osm-server.url")+"/"+Main.pref.get("osm-server.version", "0.5");
    101104                Bounds bounds = new Bounds(new LatLon(lat1, lon1), new LatLon(lat2, lon2));
    102105                        DataSource src = new DataSource(bounds, origin);
    103106                data.dataSources.add(src);
     107             */
    104108                in.close();
    105109                activeConnection = null;
  • trunk/src/org/openstreetmap/josm/io/OsmReader.java

    r633 r769  
    5050public class OsmReader {
    5151
    52         /**
    53         * This is used as (readonly) source for finding missing references when not transferred in the
    54         * file.
    55         */
    56         private DataSet references;
    57 
    58         /**
    59         * The dataset to add parsed objects to.
    60         */
    61         private DataSet ds = new DataSet();
    62 
    63         /**
    64         * The visitor to use to add the data to the set.
    65         */
    66         private AddVisitor adder = new AddVisitor(ds);
    67 
    68         /**
    69         * All read nodes after phase 1.
    70         */
    71         private Map<Long, Node> nodes = new HashMap<Long, Node>();
    72 
    73         // TODO: What the hack? Is this really from me? Please, clean this up!
    74         private static class OsmPrimitiveData extends OsmPrimitive {
    75                 @Override public void visit(Visitor visitor) {}
    76                 public int compareTo(OsmPrimitive o) {return 0;}
    77 
    78                 public void copyTo(OsmPrimitive osm) {
    79                         osm.id = id;
    80                         osm.keys = keys;
    81                         osm.modified = modified;
    82                         osm.selected = selected;
    83                         osm.deleted = deleted;
    84                         osm.timestamp = timestamp;
    85                         osm.user = user;
    86                         osm.visible = visible;
    87                         osm.version = version;
    88                         osm.checkTagged();
     52     /**
     53      * This is used as (readonly) source for finding missing references when not transferred in the
     54      * file.
     55      */
     56     private DataSet references;
     57
     58     /**
     59      * The dataset to add parsed objects to.
     60      */
     61     private DataSet ds = new DataSet();
     62
     63     /**
     64      * The visitor to use to add the data to the set.
     65      */
     66     private AddVisitor adder = new AddVisitor(ds);
     67
     68     /**
     69      * All read nodes after phase 1.
     70      */
     71     private Map<Long, Node> nodes = new HashMap<Long, Node>();
     72
     73     // TODO: What the hack? Is this really from me? Please, clean this up!
     74     private static class OsmPrimitiveData extends OsmPrimitive {
     75          @Override public void visit(Visitor visitor) {}
     76          public int compareTo(OsmPrimitive o) {return 0;}
     77
     78          public void copyTo(OsmPrimitive osm) {
     79               osm.id = id;
     80               osm.keys = keys;
     81               osm.modified = modified;
     82               osm.selected = selected;
     83               osm.deleted = deleted;
     84               osm.timestamp = timestamp;
     85               osm.user = user;
     86               osm.visible = visible;
     87               osm.version = version;
     88               osm.checkTagged();
    8989                        osm.checkDirectionTagged();
    90                 }
    91         }
    92 
    93         /**
    94          * Used as a temporary storage for relation members, before they
    95          * are resolved into pointers to real objects.
    96          */
    97         private static class RelationMemberData {
    98                 public String type;
    99                 public long id;
    100                 public RelationMember relationMember;
    101         }
    102 
    103         /**
    104          * Data structure for the remaining way objects
    105          */
    106         private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>();
    107 
    108         /**
    109          * Data structure for relation objects
    110          */
    111         private Map<OsmPrimitiveData, Collection<RelationMemberData>> relations = new HashMap<OsmPrimitiveData, Collection<RelationMemberData>>();
    112 
    113         /**
    114          * List of protocol versions that will be accepted on reading
    115          */
    116         private HashSet<String> allowedVersions = new HashSet<String>();
    117 
    118         private class Parser extends DefaultHandler {
    119                 /**
    120                  * The current osm primitive to be read.
    121                  */
    122                 private OsmPrimitive current;
    123 
    124                 @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
    125                         try {
    126                                 if (qName.equals("osm")) {
    127                                         if (atts == null)
    128                                                 throw new SAXException(tr("Unknown version"));
    129                                         if (!allowedVersions.contains(atts.getValue("version")))
    130                                                 throw new SAXException(tr("Unknown version")+": "+atts.getValue("version"));
    131                                 } else if (qName.equals("bound")) {
    132                                         String bbox = atts.getValue("box");
    133                                         String origin = atts.getValue("origin");
    134                                         if (origin == null) origin = "";
    135                                         if (bbox != null) {
    136                                                 String[] b = bbox.split(",");
    137                                                 Bounds bounds = new Bounds();
    138                                                 if (b.length == 4)
    139                                                         bounds = new Bounds(
    140                                                                         new LatLon(Double.parseDouble(b[0]),Double.parseDouble(b[1])),
    141                                                                         new LatLon(Double.parseDouble(b[2]),Double.parseDouble(b[3])));
    142                                                 DataSource src = new DataSource(bounds, origin);
    143                                                 ds.dataSources.add(src);
    144                                         }
    145                                        
    146                                 // ---- PARSING NODES AND WAYS ----
    147                                        
    148                                 } else if (qName.equals("node")) {
    149                                         current = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
    150                                         readCommon(atts, current);
    151                                         nodes.put(current.id, (Node)current);
    152                                 } else if (qName.equals("way")) {
    153                                         current = new OsmPrimitiveData();
    154                                         readCommon(atts, current);
    155                                         ways.put((OsmPrimitiveData)current, new ArrayList<Long>());
    156                                 } else if (qName.equals("nd")) {
    157                                         Collection<Long> list = ways.get(current);
    158                                         if (list == null)
    159                                                 throw new SAXException(tr("Found <nd> element in non-way."));
    160                                         long id = getLong(atts, "ref");
    161                                         if (id == 0)
    162                                                 throw new SAXException(tr("<nd> has zero ref"));
    163                                         list.add(id);
    164 
    165                                 // ---- PARSING RELATIONS ----                 
    166 
    167                                 } else if (qName.equals("relation")) {
    168                                         current = new OsmPrimitiveData();
    169                                         readCommon(atts, current);
    170                                         relations.put((OsmPrimitiveData)current, new LinkedList<RelationMemberData>());
    171                                 } else if (qName.equals("member")) {
    172                                         Collection<RelationMemberData> list = relations.get(current);
    173                                         if (list == null)
    174                                                 throw new SAXException(tr("Found <member> tag on non-relation."));
    175                                         RelationMemberData emd = new RelationMemberData();
    176                                         emd.relationMember = new RelationMember();
    177                                         emd.id = getLong(atts, "ref");
    178                                         emd.type=atts.getValue("type");
    179                                         emd.relationMember.role = atts.getValue("role");
    180                                        
    181                                         if (emd.id == 0)
    182                                                 throw new SAXException(tr("Incomplete <member> specification with ref=0"));
    183                                        
    184                                         list.add(emd);
    185                                        
    186                                 // ---- PARSING TAGS (applicable to all objects) ----
    187                                        
    188                                 } else if (qName.equals("tag")) {
    189                                         current.put(atts.getValue("k"), atts.getValue("v"));
    190                                 }
    191                         } catch (NumberFormatException x) {
    192                                 x.printStackTrace(); // SAXException does not chain correctly
    193                                 throw new SAXException(x.getMessage(), x);
    194                         } catch (NullPointerException x) {
    195                                 x.printStackTrace(); // SAXException does not chain correctly
    196                                 throw new SAXException(tr("NullPointerException, Possibly some missing tags."), x);
    197                         }
    198                 }
    199 
    200                 private double getDouble(Attributes atts, String value) {
    201                         return Double.parseDouble(atts.getValue(value));
    202                 }
    203         }
    204        
    205         /**
    206          * Constructor initializes list of allowed protocol versions.
    207          */
    208         public OsmReader() {
    209                 // first add the main server version
    210                 allowedVersions.add(Main.pref.get("osm-server.version", "0.5"));
    211                 // now also add all compatible versions
    212                 String[] additionalVersions =
    213                         Main.pref.get("osm-server.additional-versions", "").split("/,/");
    214                 if (additionalVersions.length == 1 && additionalVersions[0].length() == 0)
    215                         additionalVersions = new String[] {};
    216                 allowedVersions.addAll(Arrays.asList(additionalVersions));     
    217         }
    218 
    219         /**
    220          * Read out the common attributes from atts and put them into this.current.
    221          */
    222         void readCommon(Attributes atts, OsmPrimitive current) throws SAXException {
    223                 current.id = getLong(atts, "id");
    224                 if (current.id == 0)
    225                         throw new SAXException(tr("Illegal object with id=0"));
    226 
    227                 String time = atts.getValue("timestamp");
    228                 if (time != null && time.length() != 0) {
    229                         /* Do not parse the date here since it wastes a HUGE amount of time.
    230                          * Moved into OsmPrimitive.
    231                         try {
    232                                 current.timestamp = DateParser.parse(time);
    233                         } catch (ParseException e) {
    234                                 e.printStackTrace();
    235                                 throw new SAXException(tr("Couldn't read time format \"{0}\".",time));
    236                         }
    237                         */
    238                         current.timestamp = time;
    239                 }
    240                
    241                 // user attribute added in 0.4 API
    242                 String user = atts.getValue("user");
    243                 if (user != null) {
    244                         // do not store literally; get object reference for string
    245                         current.user = User.get(user);
    246                 }
    247                
    248                 // visible attribute added in 0.4 API
    249                 String visible = atts.getValue("visible");
    250                 if (visible != null) {
    251                         current.visible = Boolean.parseBoolean(visible);
    252                 }
    253 
    254                 // oldversion attribute added in 0.6 API
    255 
    256                 // Note there is an asymmetry here: the server will send
    257                 // the version as "version" the client sends it as
    258                 // "oldversion". So we take both since which we receive will
    259                 // depend on reading from a file or reading from the server
    260 
    261                 String version = atts.getValue("version");
    262                 if (version != null) {
    263                         current.version = Integer.parseInt(version);
    264                 }
    265                 version = atts.getValue("old_version");
    266                 if (version != null) {
    267                         current.version = Integer.parseInt(version);
    268                 }
    269 
    270                 String action = atts.getValue("action");
    271                 if (action == null)
    272                         return;
    273                 if (action.equals("delete"))
    274                         current.delete(true);
    275                 else if (action.startsWith("modify"))
    276                         current.modified = true;
    277         }
    278         private long getLong(Attributes atts, String value) throws SAXException {
    279                 String s = atts.getValue(value);
    280                 if (s == null)
    281                         throw new SAXException(tr("Missing required attribute \"{0}\".",value));
    282                 return Long.parseLong(s);
    283         }
    284 
    285         private Node findNode(long id) {
    286             Node n = nodes.get(id);
    287             if (n != null)
    288                 return n;
    289             for (Node node : references.nodes)
    290                 if (node.id == id)
    291                         return node;
    292             // TODO: This has to be changed to support multiple layers.
    293             for (Node node : Main.ds.nodes)
    294                 if (node.id == id)
    295                         return new Node(node);
    296             return null;
     90          }
     91     }
     92
     93     /**
     94      * Used as a temporary storage for relation members, before they
     95      * are resolved into pointers to real objects.
     96      */
     97     private static class RelationMemberData {
     98          public String type;
     99          public long id;
     100          public RelationMember relationMember;
     101     }
     102
     103     /**
     104      * Data structure for the remaining way objects
     105      */
     106     private Map<OsmPrimitiveData, Collection<Long>> ways = new HashMap<OsmPrimitiveData, Collection<Long>>();
     107
     108     /**
     109      * Data structure for relation objects
     110      */
     111     private Map<OsmPrimitiveData, Collection<RelationMemberData>> relations = new HashMap<OsmPrimitiveData, Collection<RelationMemberData>>();
     112
     113     /**
     114      * List of protocol versions that will be accepted on reading
     115      */
     116     private HashSet<String> allowedVersions = new HashSet<String>();
     117
     118     private class Parser extends DefaultHandler {
     119          /**
     120           * The current osm primitive to be read.
     121           */
     122          private OsmPrimitive current;
     123          private String generator;
     124
     125          @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
     126               try {
     127                    if (qName.equals("osm")) {
     128                         if (atts == null)
     129                              throw new SAXException(tr("Unknown version"));
     130                         if (!allowedVersions.contains(atts.getValue("version")))
     131                              throw new SAXException(tr("Unknown version")+": "+atts.getValue("version"));
     132                         // save generator attribute for later use when creating DataSource objects
     133                         generator = atts.getValue("generator");
     134
     135                         
     136                    } else if (qName.equals("bound")) {
     137                         // old style bounds.
     138                         // TODO: remove this around 1st October 2008.
     139                         // - this is a bit of a hack; since we still write out old style bound objects,
     140                         // we don't want to load them both. so when writing, we add a "note" tag the our
     141                         // old-style bound, and when reading, ignore those with a "note".
     142                         String note = atts.getValue("note");
     143                         if (note == null) {
     144                             System.out.println("Notice: old style <bound> element detected; support for these will be dropped in a future release.");
     145                             String bbox = atts.getValue("box");
     146                             String origin = atts.getValue("origin");
     147                             if (origin == null) origin = "";
     148                             if (bbox != null) {
     149                                  String[] b = bbox.split(",");
     150                                  Bounds bounds = new Bounds();
     151                                  if (b.length == 4)
     152                                       bounds = new Bounds(
     153                                                 new LatLon(Double.parseDouble(b[0]),Double.parseDouble(b[1])),
     154                                                 new LatLon(Double.parseDouble(b[2]),Double.parseDouble(b[3])));
     155                                  DataSource src = new DataSource(bounds, origin);
     156                                  ds.dataSources.add(src);
     157                             }
     158                         }
     159                    } else if (qName.equals("bounds")) {
     160                         // new style bounds.
     161                         String minlon = atts.getValue("minlon");
     162                         String minlat = atts.getValue("minlat");
     163                         String maxlon = atts.getValue("maxlon");
     164                         String maxlat = atts.getValue("maxlat");
     165                         String origin = atts.getValue("origin");
     166                         if (minlon != null && maxlon != null && minlat != null && maxlat != null) {
     167                              if (origin == null) origin = generator;
     168                              Bounds bounds = new Bounds(
     169                                  new LatLon(Double.parseDouble(minlat), Double.parseDouble(minlon)),
     170                                  new LatLon(Double.parseDouble(maxlat), Double.parseDouble(maxlon)));
     171                              DataSource src = new DataSource(bounds, origin);
     172                              ds.dataSources.add(src);
     173                         }
     174                         
     175                    // ---- PARSING NODES AND WAYS ----
     176                         
     177                    } else if (qName.equals("node")) {
     178                         current = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
     179                         readCommon(atts, current);
     180                         nodes.put(current.id, (Node)current);
     181                    } else if (qName.equals("way")) {
     182                         current = new OsmPrimitiveData();
     183                         readCommon(atts, current);
     184                         ways.put((OsmPrimitiveData)current, new ArrayList<Long>());
     185                    } else if (qName.equals("nd")) {
     186                         Collection<Long> list = ways.get(current);
     187                         if (list == null)
     188                              throw new SAXException(tr("Found <nd> element in non-way."));
     189                         long id = getLong(atts, "ref");
     190                         if (id == 0)
     191                              throw new SAXException(tr("<nd> has zero ref"));
     192                         list.add(id);
     193
     194                    // ---- PARSING RELATIONS ----               
     195
     196                    } else if (qName.equals("relation")) {
     197                         current = new OsmPrimitiveData();
     198                         readCommon(atts, current);
     199                         relations.put((OsmPrimitiveData)current, new LinkedList<RelationMemberData>());
     200                    } else if (qName.equals("member")) {
     201                         Collection<RelationMemberData> list = relations.get(current);
     202                         if (list == null)
     203                              throw new SAXException(tr("Found <member> tag on non-relation."));
     204                         RelationMemberData emd = new RelationMemberData();
     205                         emd.relationMember = new RelationMember();
     206                         emd.id = getLong(atts, "ref");
     207                         emd.type=atts.getValue("type");
     208                         emd.relationMember.role = atts.getValue("role");
     209                         
     210                         if (emd.id == 0)
     211                              throw new SAXException(tr("Incomplete <member> specification with ref=0"));
     212                         
     213                         list.add(emd);
     214                         
     215                    // ---- PARSING TAGS (applicable to all objects) ----
     216                         
     217                    } else if (qName.equals("tag")) {
     218                         current.put(atts.getValue("k"), atts.getValue("v"));
     219                    }
     220               } catch (NumberFormatException x) {
     221                    x.printStackTrace(); // SAXException does not chain correctly
     222                    throw new SAXException(x.getMessage(), x);
     223               } catch (NullPointerException x) {
     224                    x.printStackTrace(); // SAXException does not chain correctly
     225                    throw new SAXException(tr("NullPointerException, Possibly some missing tags."), x);
     226               }
     227          }
     228
     229          private double getDouble(Attributes atts, String value) {
     230               return Double.parseDouble(atts.getValue(value));
     231          }
     232     }
     233     
     234     /**
     235      * Constructor initializes list of allowed protocol versions.
     236      */
     237     public OsmReader() {
     238          // first add the main server version
     239          allowedVersions.add(Main.pref.get("osm-server.version", "0.5"));
     240          // now also add all compatible versions
     241          String[] additionalVersions =
     242               Main.pref.get("osm-server.additional-versions", "").split("/,/");
     243          if (additionalVersions.length == 1 && additionalVersions[0].length() == 0)
     244               additionalVersions = new String[] {};
     245          allowedVersions.addAll(Arrays.asList(additionalVersions));     
     246     }
     247
     248     /**
     249      * Read out the common attributes from atts and put them into this.current.
     250      */
     251     void readCommon(Attributes atts, OsmPrimitive current) throws SAXException {
     252          current.id = getLong(atts, "id");
     253          if (current.id == 0)
     254               throw new SAXException(tr("Illegal object with id=0"));
     255
     256          String time = atts.getValue("timestamp");
     257          if (time != null && time.length() != 0) {
     258               /* Do not parse the date here since it wastes a HUGE amount of time.
     259                * Moved into OsmPrimitive.
     260               try {
     261                    current.timestamp = DateParser.parse(time);
     262               } catch (ParseException e) {
     263                    e.printStackTrace();
     264                    throw new SAXException(tr("Couldn't read time format \"{0}\".",time));
     265               }
     266               */
     267               current.timestamp = time;
     268          }
     269         
     270          // user attribute added in 0.4 API
     271          String user = atts.getValue("user");
     272          if (user != null) {
     273               // do not store literally; get object reference for string
     274               current.user = User.get(user);
     275          }
     276         
     277          // visible attribute added in 0.4 API
     278          String visible = atts.getValue("visible");
     279          if (visible != null) {
     280               current.visible = Boolean.parseBoolean(visible);
     281          }
     282
     283          // oldversion attribute added in 0.6 API
     284
     285          // Note there is an asymmetry here: the server will send
     286          // the version as "version" the client sends it as
     287          // "oldversion". So we take both since which we receive will
     288          // depend on reading from a file or reading from the server
     289
     290          String version = atts.getValue("version");
     291          if (version != null) {
     292               current.version = Integer.parseInt(version);
     293          }
     294          version = atts.getValue("old_version");
     295          if (version != null) {
     296               current.version = Integer.parseInt(version);
     297          }
     298
     299          String action = atts.getValue("action");
     300          if (action == null)
     301               return;
     302          if (action.equals("delete"))
     303               current.delete(true);
     304          else if (action.startsWith("modify"))
     305               current.modified = true;
     306     }
     307     private long getLong(Attributes atts, String value) throws SAXException {
     308          String s = atts.getValue(value);
     309          if (s == null)
     310               throw new SAXException(tr("Missing required attribute \"{0}\".",value));
     311          return Long.parseLong(s);
     312     }
     313
     314     private Node findNode(long id) {
     315         Node n = nodes.get(id);
     316         if (n != null)
     317              return n;
     318         for (Node node : references.nodes)
     319              if (node.id == id)
     320                   return node;
     321         // TODO: This has to be changed to support multiple layers.
     322         for (Node node : Main.ds.nodes)
     323              if (node.id == id)
     324                   return new Node(node);
     325         return null;
    297326    }
    298327
    299         private void createWays() {
    300                 for (Entry<OsmPrimitiveData, Collection<Long>> e : ways.entrySet()) {
    301                         Way w = new Way();
    302                         boolean failed = false;
    303                         for (long id : e.getValue()) {
    304                                 Node n = findNode(id);
    305                                 if (n == null) {
    306                                         failed = true;
    307                                         break;
    308                                 }
    309                                 w.nodes.add(n);
    310                         }
    311                         if (failed) continue;
    312                         e.getKey().copyTo(w);
    313                         adder.visit(w);
    314                 }
    315                
    316         }
    317 
    318         /**
    319         * Return the Way object with the given id, or null if it doesn't
    320         * exist yet. This method only looks at ways stored in the data set.
    321         *
    322         * @param id
    323         * @return way object or null
    324         */
    325         private Way findWay(long id) {
    326                 for (Way wy : ds.ways)
    327                         if (wy.id == id)
    328                                 return wy;
    329                 for (Way wy : Main.ds.ways)
    330                         if (wy.id == id)
    331                                 return wy;
    332                 return null;
    333         }
    334 
    335         /**
    336         * Return the Relation object with the given id, or null if it doesn't
    337         * exist yet. This method only looks at relations stored in the data set.
    338         *
    339         * @param id
    340         * @return relation object or null
    341         */
    342         private Relation findRelation(long id) {
    343                 for (Relation e : ds.relations)
    344                         if (e.id == id)
    345                                 return e;
    346                 for (Relation e : Main.ds.relations)
    347                         if (e.id == id)
    348                                 return e;
    349                 return null;
    350         }
    351 
    352         /**
    353         * Create relations. This is slightly different than n/s/w because
    354         * unlike other objects, relations may reference other relations; it
    355         * is not guaranteed that a referenced relation will have been created
    356         * before it is referenced. So we have to create all relations first,
    357         * and populate them later.
    358         */
    359         private void createRelations() {
    360                
    361                 // pass 1 - create all relations
    362                 for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) {
    363                         Relation en = new Relation();
    364                         e.getKey().copyTo(en);
    365                         adder.visit(en);
    366                 }
    367 
    368                 // pass 2 - sort out members
    369                 for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) {
    370                         Relation en = findRelation(e.getKey().id);
    371                         if (en == null) throw new Error("Failed to create relation " + e.getKey().id);
    372                        
    373                         for (RelationMemberData emd : e.getValue()) {
    374                                 RelationMember em = emd.relationMember;
    375                                 if (emd.type.equals("node")) {
    376                                         em.member = findNode(emd.id);
    377                                         if (em.member == null) {
    378                                                 em.member = new Node(emd.id);
    379                                                 adder.visit((Node)em.member);
    380                                         }
    381                                 } else if (emd.type.equals("way")) {
    382                                         em.member = findWay(emd.id);
    383                                         if (em.member == null) {
    384                                                 em.member = new Way(emd.id);
    385                                                 adder.visit((Way)em.member);
    386                                         }
    387                                 } else if (emd.type.equals("relation")) {
    388                                         em.member = findRelation(emd.id);
    389                                         if (em.member == null) {
    390                                                 em.member = new Relation(emd.id);
    391                                                 adder.visit((Relation)em.member);
    392                                         }
    393                                 } else {
    394                                         // this is an error.
    395                                 }
    396                                 en.members.add(em);
    397                         }
    398                 }
    399         }
    400 
    401         /**
    402         * Parse the given input source and return the dataset.
    403         * @param ref The dataset that is search in for references first. If
    404          *      the Reference is not found here, Main.ds is searched and a copy of the
    405         *  elemet found there is returned.
    406         */
    407         public static DataSet parseDataSet(InputStream source, DataSet ref, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException {
    408                 OsmReader osm = new OsmReader();
    409                 osm.references = ref == null ? new DataSet() : ref;
    410 
    411                 // phase 1: Parse nodes and read in raw ways
    412                 InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
    413                 try {
    414                 SAXParserFactory.newInstance().newSAXParser().parse(inputSource, osm.new Parser());
     328     private void createWays() {
     329          for (Entry<OsmPrimitiveData, Collection<Long>> e : ways.entrySet()) {
     330               Way w = new Way();
     331               boolean failed = false;
     332               for (long id : e.getValue()) {
     333                    Node n = findNode(id);
     334                    if (n == null) {
     335                         failed = true;
     336                         break;
     337                    }
     338                    w.nodes.add(n);
     339               }
     340               if (failed) continue;
     341               e.getKey().copyTo(w);
     342               adder.visit(w);
     343          }
     344         
     345     }
     346
     347     /**
     348      * Return the Way object with the given id, or null if it doesn't
     349      * exist yet. This method only looks at ways stored in the data set.
     350      *
     351      * @param id
     352      * @return way object or null
     353      */
     354     private Way findWay(long id) {
     355          for (Way wy : ds.ways)
     356               if (wy.id == id)
     357                    return wy;
     358          for (Way wy : Main.ds.ways)
     359               if (wy.id == id)
     360                    return wy;
     361          return null;
     362     }
     363
     364     /**
     365      * Return the Relation object with the given id, or null if it doesn't
     366      * exist yet. This method only looks at relations stored in the data set.
     367      *
     368      * @param id
     369      * @return relation object or null
     370      */
     371     private Relation findRelation(long id) {
     372          for (Relation e : ds.relations)
     373               if (e.id == id)
     374                    return e;
     375          for (Relation e : Main.ds.relations)
     376               if (e.id == id)
     377                    return e;
     378          return null;
     379     }
     380
     381     /**
     382      * Create relations. This is slightly different than n/s/w because
     383      * unlike other objects, relations may reference other relations; it
     384      * is not guaranteed that a referenced relation will have been created
     385      * before it is referenced. So we have to create all relations first,
     386      * and populate them later.
     387      */
     388     private void createRelations() {
     389         
     390          // pass 1 - create all relations
     391          for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) {
     392               Relation en = new Relation();
     393               e.getKey().copyTo(en);
     394               adder.visit(en);
     395          }
     396
     397          // pass 2 - sort out members
     398          for (Entry<OsmPrimitiveData, Collection<RelationMemberData>> e : relations.entrySet()) {
     399               Relation en = findRelation(e.getKey().id);
     400               if (en == null) throw new Error("Failed to create relation " + e.getKey().id);
     401               
     402               for (RelationMemberData emd : e.getValue()) {
     403                    RelationMember em = emd.relationMember;
     404                    if (emd.type.equals("node")) {
     405                         em.member = findNode(emd.id);
     406                         if (em.member == null) {
     407                              em.member = new Node(emd.id);
     408                              adder.visit((Node)em.member);
     409                         }
     410                    } else if (emd.type.equals("way")) {
     411                         em.member = findWay(emd.id);
     412                         if (em.member == null) {
     413                              em.member = new Way(emd.id);
     414                              adder.visit((Way)em.member);
     415                         }
     416                    } else if (emd.type.equals("relation")) {
     417                         em.member = findRelation(emd.id);
     418                         if (em.member == null) {
     419                              em.member = new Relation(emd.id);
     420                              adder.visit((Relation)em.member);
     421                         }
     422                    } else {
     423                         // this is an error.
     424                    }
     425                    en.members.add(em);
     426               }
     427          }
     428     }
     429
     430     /**
     431      * Parse the given input source and return the dataset.
     432      * @param ref The dataset that is search in for references first. If
     433      *      the Reference is not found here, Main.ds is searched and a copy of the
     434      *  elemet found there is returned.
     435      */
     436     public static DataSet parseDataSet(InputStream source, DataSet ref, PleaseWaitDialog pleaseWaitDlg) throws SAXException, IOException {
     437          OsmReader osm = new OsmReader();
     438          osm.references = ref == null ? new DataSet() : ref;
     439
     440          // phase 1: Parse nodes and read in raw ways
     441          InputSource inputSource = new InputSource(new InputStreamReader(source, "UTF-8"));
     442          try {
     443             SAXParserFactory.newInstance().newSAXParser().parse(inputSource, osm.new Parser());
    415444        } catch (ParserConfigurationException e1) {
    416                 e1.printStackTrace(); // broken SAXException chaining
    417                 throw new SAXException(e1);
     445             e1.printStackTrace(); // broken SAXException chaining
     446             throw new SAXException(e1);
    418447        }
    419448
    420449        if (pleaseWaitDlg != null) {
    421                         pleaseWaitDlg.progress.setValue(0);
    422                         pleaseWaitDlg.currentAction.setText(tr("Preparing data..."));
    423                 }
    424 
    425                 for (Node n : osm.nodes.values())
    426                         osm.adder.visit(n);
    427 
    428                 try {
    429                         osm.createWays();
    430                         osm.createRelations();
    431                 } catch (NumberFormatException e) {
    432                         e.printStackTrace();
    433                         throw new SAXException(tr("Illformed Node id"));
    434                 }
    435 
    436                 // clear all negative ids (new to this file)
    437                 for (OsmPrimitive o : osm.ds.allPrimitives())
    438                         if (o.id < 0)
    439                                 o.id = 0;
    440 
    441                 return osm.ds;
    442         }
     450               pleaseWaitDlg.progress.setValue(0);
     451               pleaseWaitDlg.currentAction.setText(tr("Preparing data..."));
     452          }
     453
     454          for (Node n : osm.nodes.values())
     455               osm.adder.visit(n);
     456
     457          try {
     458               osm.createWays();
     459               osm.createRelations();
     460          } catch (NumberFormatException e) {
     461               e.printStackTrace();
     462               throw new SAXException(tr("Illformed Node id"));
     463          }
     464
     465          // clear all negative ids (new to this file)
     466          for (OsmPrimitive o : osm.ds.allPrimitives())
     467               if (o.id < 0)
     468                    o.id = 0;
     469
     470          return osm.ds;
     471     }
    443472}
  • trunk/src/org/openstreetmap/josm/io/OsmWriter.java

    r627 r769  
    9494                super.header(out);
    9595                        for (DataSource s : ds.dataSources) {
    96                                 out.print("  <bound box='"+
     96                // TODO: remove <bound> output after a grace period (1st October 08)
     97                                out.print("  <bound note='this tag is deprecated and only provided for backward compatiblity' box='"+
    9798                                                s.bounds.min.lat()+","+
    9899                                                s.bounds.min.lon()+","+
    99100                                                s.bounds.max.lat()+","+
     101                                                s.bounds.max.lon()+"' ");
     102                                out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
     103                                out.print("  <bounds minlat='" +
     104                                                s.bounds.min.lat()+"' minlon='"+
     105                                                s.bounds.min.lon()+"' maxlat='"+
     106                                                s.bounds.max.lat()+"' maxlon='"+
    100107                                                s.bounds.max.lon()+"' ");
    101108                                out.println("origin='"+XmlWriter.encode(s.origin)+"' />");
Note: See TracChangeset for help on using the changeset viewer.