@Override
 protected void cancel() {
   canceled = true;
   synchronized (this) {
     if (multiObjectReader != null) {
       multiObjectReader.cancel();
     }
     if (objectReader != null) {
       objectReader.cancel();
     }
   }
 }
 protected void loadIncompleteNodes() throws OsmTransferException {
   // a way loaded with MultiFetch may have incomplete nodes because at least one of its
   // nodes isn't present in the local data set. We therefore fully load all ways with incomplete
   // nodes.
   for (Way w : ds.getWays()) {
     if (canceled) return;
     if (w.hasIncompleteNodes()) {
       synchronized (this) {
         if (canceled) return;
         objectReader =
             new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
       }
       DataSet theirDataSet =
           objectReader.parseOsm(
               progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
       synchronized (this) {
         objectReader = null;
       }
       new DataSetMerger(ds, theirDataSet).merge();
     }
   }
 }
 protected void loadIncompleteRelationMembers() throws OsmTransferException {
   // if incomplete relation members exist, download them too
   for (Relation r : ds.getRelations()) {
     if (canceled) return;
     // Relations may be incomplete in case of nested relations if child relations are accessed
     // before their parent
     // (it may happen because "relations" has no deterministic sort order, see #10388)
     if (r.isIncomplete() || r.hasIncompleteMembers()) {
       synchronized (this) {
         if (canceled) return;
         objectReader =
             new OsmServerObjectReader(r.getId(), OsmPrimitiveType.RELATION, fullRelation);
       }
       DataSet theirDataSet =
           objectReader.parseOsm(
               progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
       synchronized (this) {
         objectReader = null;
       }
       new DataSetMerger(ds, theirDataSet).merge();
     }
   }
 }