gt:     protected Way parseWay() throws XMLStreamException {
context: // License: GPL. See LICENSE file for details.
  package org.openstreetmap.josm.io;
  
  import static org.openstreetmap.josm.tools.I18n.tr;
  
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.text.MessageFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import javax.xml.stream.Location;
  import javax.xml.stream.XMLInputFactory;
  import javax.xml.stream.XMLStreamConstants;
  import javax.xml.stream.XMLStreamException;
  import javax.xml.stream.XMLStreamReader;
  
  import org.openstreetmap.josm.Main;
  import org.openstreetmap.josm.data.Bounds;
  import org.openstreetmap.josm.data.coor.LatLon;
  import org.openstreetmap.josm.data.osm.Changeset;
  import org.openstreetmap.josm.data.osm.DataSet;
  import org.openstreetmap.josm.data.osm.DataSource;
  import org.openstreetmap.josm.data.osm.Node;
  import org.openstreetmap.josm.data.osm.NodeData;
  import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
  import org.openstreetmap.josm.data.osm.PrimitiveData;
  import org.openstreetmap.josm.data.osm.Relation;
  import org.openstreetmap.josm.data.osm.RelationData;
  import org.openstreetmap.josm.data.osm.RelationMemberData;
  import org.openstreetmap.josm.data.osm.Tagged;
  import org.openstreetmap.josm.data.osm.User;
  import org.openstreetmap.josm.data.osm.Way;
  import org.openstreetmap.josm.data.osm.WayData;
  import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
  import org.openstreetmap.josm.gui.progress.ProgressMonitor;
  import org.openstreetmap.josm.tools.CheckParameterUtil;
  import org.openstreetmap.josm.tools.DateUtils;
  
  /**
   * Parser for the Osm Api. Read from an input stream and construct a dataset out of it.
   *
   * For each xml element, there is a dedicated method.
   * The XMLStreamReader cursor points to the start of the element, when the method is
   * entered, and it must point to the end of the same element, when it is exited.
   */
  public class OsmReader extends AbstractReader {
  
      protected XMLStreamReader parser;
  
      protected boolean cancel;
  
      /** Used by plugins to register themselves as data postprocessors. */
      public static List<OsmServerReadPostprocessor> postprocessors;
  
      /** register a new postprocessor */
      public static void registerPostprocessor(OsmServerReadPostprocessor pp) {
          if (postprocessors == null) {
              postprocessors = new ArrayList<OsmServerReadPostprocessor>();
          }
          postprocessors.add(pp);
      }
  
      /** deregister a postprocessor previously registered with registerPostprocessor */
      public static void deregisterPostprocessor(OsmServerReadPostprocessor pp) {
          if (postprocessors != null) {
              postprocessors.remove(pp);
          }
      }
  
      /**
       * constructor (for private and subclasses use only)
       *
       * @see #parseDataSet(InputStream, ProgressMonitor)
       */
      protected OsmReader() {
      }
  
      protected void setParser(XMLStreamReader parser) {
          this.parser = parser;
      }
  
      protected void throwException(String msg, Throwable th) throws XMLStreamException {
          throw new OsmParsingException(msg, parser.getLocation(), th);
      }
  
      protected void throwException(String msg) throws XMLStreamException {
          throw new OsmParsingException(msg, parser.getLocation());
      }
  
      protected void parse() throws XMLStreamException {
          int event = parser.getEventType();
          while (true) {
              if (event == XMLStreamConstants.START_ELEMENT) {
                  parseRoot();
              } else if (event == XMLStreamConstants.END_ELEMENT)
                  return;
              if (parser.hasNext()) {
                  event = parser.next();
              } else {
                  break;
              }
          }
          parser.close();
      }
  
      protected void parseRoot() throws XMLStreamException {
          if (parser.getLocalName().equals("osm")) {
              parseOsm();
          } else {
              parseUnknown();
          }
      }
  
      private void parseOsm() throws XMLStreamException {
          String v = parser.getAttributeValue(null, "version");
          if (v == null) {
              throwException(tr("Missing mandatory attribute ''{0}''.", "version"));
          }
          if (!(v.equals("0.5") || v.equals("0.6"))) {
              throwException(tr("Unsupported version: {0}", v));
          }
          ds.setVersion(v);
          String upload = parser.getAttributeValue(null, "upload");
          if (upload != null) {
              ds.setUploadDiscouraged(!Boolean.parseBoolean(upload));
          }
          String generator = parser.getAttributeValue(null, "generator");
          Long uploadChangesetId = null;
          if (parser.getAttributeValue(null, "upload-changeset") != null) {
              uploadChangesetId = getLong("upload-changeset");
          }
          while (true) {
              int event = parser.next();
  
              if (cancel) {
                  cancel = false;
                  throw new OsmParsingCanceledException(tr("Reading was canceled"), parser.getLocation());
              }
  
              if (event == XMLStreamConstants.START_ELEMENT) {
                  if (parser.getLocalName().equals("bounds")) {
                      parseBounds(generator);
                  } else if (parser.getLocalName().equals("node")) {
                      parseNode();
                  } else if (parser.getLocalName().equals("way")) {
                      parseWay();
                  } else if (parser.getLocalName().equals("relation")) {
                      parseRelation();
                  } else if (parser.getLocalName().equals("changeset")) {
                      parseChangeset(uploadChangesetId);
                  } else {
                      parseUnknown();
                  }
              } else if (event == XMLStreamConstants.END_ELEMENT)
                  return;
          }
      }
  
      private void parseBounds(String generator) throws XMLStreamException {
          String minlon = parser.getAttributeValue(null, "minlon");
          String minlat = parser.getAttributeValue(null, "minlat");
          String maxlon = parser.getAttributeValue(null, "maxlon");
          String maxlat = parser.getAttributeValue(null, "maxlat");
          String origin = parser.getAttributeValue(null, "origin");
          if (minlon != null && maxlon != null && minlat != null && maxlat != null) {
              if (origin == null) {
                  origin = generator;
              }
              Bounds bounds = new Bounds(
                      Double.parseDouble(minlat), Double.parseDouble(minlon),
                      Double.parseDouble(maxlat), Double.parseDouble(maxlon));
              if (bounds.isOutOfTheWorld()) {
                  Bounds copy = new Bounds(bounds);
                  bounds.normalize();
                  Main.info("Bbox " + copy + " is out of the world, normalized to " + bounds);
              }
              DataSource src = new DataSource(bounds, origin);
              ds.dataSources.add(src);
          } else {
              throwException(tr(
                      "Missing mandatory attributes on element ''bounds''. Got minlon=''{0}'',minlat=''{1}'',maxlon=''{3}'',maxlat=''{4}'', origin=''{5}''.",
                      minlon, minlat, maxlon, maxlat, origin
              ));
          }
          jumpToEnd();
      }
  
      protected Node parseNode() throws XMLStreamException {
          NodeData nd = new NodeData();
          String lat = parser.getAttributeValue(null, "lat");
          String lon = parser.getAttributeValue(null, "lon");
          if (lat != null && lon != null) {
              nd.setCoor(new LatLon(Double.parseDouble(lat), Double.parseDouble(lon)));
          }
          readCommon(nd);
          Node n = new Node(nd.getId(), nd.getVersion());
          n.setVisible(nd.isVisible());
          n.load(nd);
          externalIdMap.put(nd.getPrimitiveId(), n);
          while (true) {
              int event = parser.next();
              if (event == XMLStreamConstants.START_ELEMENT) {
                  if (parser.getLocalName().equals("tag")) {
                      parseTag(n);
                  } else {
                      parseUnknown();
                  }
              } else if (event == XMLStreamConstants.END_ELEMENT)
                  return n;
          }
      }
  
  