@Override
 protected void parseNodes(List<Osmformat.Node> osmNodes) {
   if (exception == null) {
     try {
       for (Osmformat.Node n : osmNodes) {
         final Info info = n.getInfo();
         if (!info.hasVersion()) discourageUpload = true;
         final Node node = new Node(n.getId(), info.hasVersion() ? info.getVersion() : 1);
         node.setCoor(
             new LatLon(parseLat(n.getLat()), parseLon(n.getLon())).getRoundedToOsmPrecision());
         checkCoordinates(node.getCoor());
         setMetadata(node, info);
         Map<String, String> keys = new HashMap<>();
         for (int i = 0; i < n.getKeysCount(); i++) {
           keys.put(getStringById(n.getKeys(i)), getStringById(n.getVals(i)));
         }
         node.setKeys(keys);
         externalIdMap.put(node.getPrimitiveId(), node);
       }
     } catch (IllegalDataException e) {
       exception = e;
     }
   }
 }
 @Override
 protected void parseDense(DenseNodes nodes) {
   if (!nodes.hasDenseinfo()) discourageUpload = true;
   if (exception == null) {
     try {
       int keyIndex = 0;
       // Almost all data is DELTA coded
       long nodeId = 0;
       long nodeLat = 0;
       long nodeLon = 0;
       long changesetId = 0;
       int uid = 0;
       int suid = 0;
       long timestamp = 0;
       for (int i = 0; i < nodes.getIdCount(); i++) {
         // Id (delta) and version (normal)
         Node node =
             new Node(
                 nodeId += nodes.getId(i),
                 nodes.hasDenseinfo() ? nodes.getDenseinfo().getVersion(i) : 1);
         // Lat/Lon (delta)
         node.setCoor(
             new LatLon(
                     parseLat(nodeLat += nodes.getLat(i)), parseLon(nodeLon += nodes.getLon(i)))
                 .getRoundedToOsmPrecision());
         checkCoordinates(node.getCoor());
         if (nodes.hasDenseinfo()) {
           DenseInfo info = nodes.getDenseinfo();
           // Changeset (delta)
           if (info.getChangesetCount() > i) {
             checkChangesetId(changesetId += info.getChangeset(i));
             node.setChangesetId((int) changesetId);
           }
           // User (delta)
           if (info.getUidCount() > i && info.getUserSidCount() > i) {
             node.setUser(
                 User.createOsmUser(
                     uid += info.getUid(i), getStringById(suid += info.getUserSid(i))));
           }
           // Timestamp (delta)
           if (info.getTimestampCount() > i) {
             checkTimestamp(timestamp += info.getTimestamp(i));
             node.setTimestamp(new Date(date_granularity * timestamp));
           }
         }
         // A single table contains all keys/values of all nodes.
         // Each node's tags are encoded in alternating <key_id> <value_id>.
         // A single stringid of 0 delimit when the tags of a node ends and the tags of the next
         // node begin.
         Map<String, String> keys = new HashMap<>();
         while (keyIndex < nodes.getKeysValsCount()) {
           int keyId = nodes.getKeysVals(keyIndex++);
           if (keyId == 0) {
             break; // End of current node's tags
           } else if (keyIndex < nodes.getKeysValsCount()) {
             keys.put(getStringById(keyId), getStringById(nodes.getKeysVals(keyIndex++)));
           } else {
             throw new IllegalDataException(tr("Invalid DenseNodes key/values table"));
           }
         }
         node.setKeys(keys);
         externalIdMap.put(node.getPrimitiveId(), node);
       }
     } catch (IllegalDataException e) {
       exception = e;
     }
   }
 }