Changeset 36318 in osm


Ignore:
Timestamp:
2024-08-21T22:32:24+02:00 (5 months ago)
Author:
taylor.smock
Message:

Clean up some lint issues in reverter

Location:
applications/editors/josm/plugins/reverter/src/reverter
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/reverter/src/reverter/ChangesetReverter.java

    r36237 r36318  
    1414import java.util.List;
    1515import java.util.Map;
     16import java.util.Objects;
    1617import java.util.Optional;
    1718import java.util.stream.Collectors;
     
    5657public class ChangesetReverter {
    5758
     59    /** The type of reversion */
    5860    public enum RevertType {
    5961        FULL,
     
    6769            ));
    6870
     71    /** The id of the changeset */
    6972    public final int changesetId;
     73    /** The changeset to be reverted */
    7074    public final Changeset changeset;
     75    /** The reversion type */
    7176    public final RevertType revertType;
    7277
    73     private final OsmDataLayer layer; // data layer associated with reverter
    74     private final DataSet ds; // DataSet associated with reverter
    75     private final ChangesetDataSet cds; // Current changeset data
     78    /** data layer associated with reverter */
     79    private final OsmDataLayer layer;
     80    /** DataSet associated with reverter */
     81    private final DataSet ds;
     82    /** Current changeset data */
     83    private final ChangesetDataSet cds;
    7684    /** original DataSet, used if a new layer is requested */
    7785    private final DataSet ods;
    78     private DataSet nds; // Dataset that contains new objects downloaded by reverter
     86    /** Dataset that contains new objects downloaded by reverter */
     87    private DataSet nds;
    7988
    8089    private final HashSet<PrimitiveId> missing = new HashSet<>();
     
    8796    //// Handling missing objects
    8897    ////////////////////////////////////////
     98
     99    /**
     100     * Add a primitive that is not in {@link #ds} to {@link #missing}
     101     * @param id The primitive to add if missing
     102     */
    89103    private void addIfMissing(PrimitiveId id) {
    90104        OsmPrimitive p = ds.getPrimitiveById(id);
     
    94108    }
    95109
     110    /**
     111     * Add missing primitives to {@link #missing}
     112     * @param primitives The primitives to iterate through
     113     */
    96114    private void addMissingHistoryIds(Iterable<HistoryOsmPrimitive> primitives) {
    97115        for (HistoryOsmPrimitive p : primitives) {
     
    100118    }
    101119
     120    /**
     121     * Add missing necessary primitives to {@link #missing}
     122     * @param p The primitive to look at
     123     */
    102124    private void addMissingId(OsmPrimitive p) {
    103125        addIfMissing(p);
     
    171193        }
    172194
    173         // Build our own lists of created/updated/modified objects for better performance
     195        buildCreatedUpdatedModifiedObjectLists();
     196    }
     197
     198    /**
     199     * Build our own lists of created/updated/modified objects for better performance
     200     */
     201    private void buildCreatedUpdatedModifiedObjectLists() {
    174202        for (PrimitiveId id : cds.getIds()) {
    175203            ChangesetDataSetEntry first = cds.getFirstEntry(id);
     
    189217    }
    190218
     219    /**
     220     * Add missing primitives that have been created
     221     */
    191222    public void checkMissingCreated() {
    192223        addMissingHistoryIds(created);
    193224    }
    194225
     226    /**
     227     * Add missing primitives that have been updated
     228     */
    195229    public void checkMissingUpdated() {
    196230        addMissingHistoryIds(updated);
    197231    }
    198232
     233    /**
     234     * Add missing primitives that have been deleted
     235     */
    199236    public void checkMissingDeleted() {
    200237        addMissingHistoryIds(deleted);
     
    237274            if (progressMonitor.isCanceled()) return;
    238275            nds = rdr.parseOsm(progressMonitor.createSubTaskMonitor(1, true));
    239             ds.update(() -> {
    240                 for (OsmPrimitive p : nds.allPrimitives()) {
    241                     if (!p.isIncomplete()) {
    242                         addMissingId(p);
    243                     } else {
    244                         if (ds.getPrimitiveById(p.getPrimitiveId()) == null) {
    245                             switch (p.getType()) {
    246                             case NODE: ds.addPrimitive(new Node(p.getUniqueId())); break;
    247                             case CLOSEDWAY:
    248                             case WAY: ds.addPrimitive(new Way(p.getUniqueId())); break;
    249                             case MULTIPOLYGON:
    250                             case RELATION: ds.addPrimitive(new Relation(p.getUniqueId())); break;
    251                             default: throw new AssertionError();
    252                             }
    253                         }
    254                     }
    255                 }
    256             });
     276            ds.update(this::addPartialPrimitives);
    257277        } finally {
    258278            progressMonitor.finishTask();
     
    260280    }
    261281
     282    /**
     283     * Add partial primitives if they are incomplete in {@link #nds}
     284     */
     285    private void addPartialPrimitives() {
     286        for (OsmPrimitive p : nds.allPrimitives()) {
     287            if (!p.isIncomplete()) {
     288                addMissingId(p);
     289            } else {
     290                if (ds.getPrimitiveById(p.getPrimitiveId()) == null) {
     291                    switch (p.getType()) {
     292                        case NODE: ds.addPrimitive(new Node(p.getUniqueId())); break;
     293                        case CLOSEDWAY:
     294                        case WAY: ds.addPrimitive(new Way(p.getUniqueId())); break;
     295                        case MULTIPOLYGON:
     296                        case RELATION: ds.addPrimitive(new Relation(p.getUniqueId())); break;
     297                        default: throw new AssertionError();
     298                    }
     299                }
     300            }
     301        }
     302    }
     303
     304    /**
     305     * Download any missing primitives we have
     306     * @param monitor The monitor to update with our progress
     307     * @throws OsmTransferException If there is an issue transferring data from OSM
     308     */
    262309    public void downloadMissingPrimitives(ProgressMonitor monitor) throws OsmTransferException {
    263310        if (!hasMissingObjects()) return;
     
    308355        switch (current.getType()) {
    309356        case NODE:
    310             LatLon currentCoor = ((Node) current).getCoor();
    311             LatLon historyCoor = ((HistoryNode) history).getCoords();
    312             if (currentCoor == historyCoor || (currentCoor != null && historyCoor != null && currentCoor.equals(historyCoor)))
    313                 return true;
    314             // Handle case where a deleted note has been restored to avoid false conflicts (fix #josm8660)
    315             if (currentCoor != null && historyCoor == null) {
    316                 LatLon previousCoor = ((Node) nds.getPrimitiveById(history.getPrimitiveId())).getCoor();
    317                 return previousCoor != null && previousCoor.equals(currentCoor);
    318             }
    319             return false;
     357            return hasEqualSemanticAttributesNode(nds, (HistoryNode) history, (Node) current);
    320358        case CLOSEDWAY:
    321359        case WAY:
    322             List<Node> currentNodes = ((Way) current).getNodes();
    323             List<Long> historyNodes = ((HistoryWay) history).getNodes();
    324             if (currentNodes.size() != historyNodes.size()) return false;
    325             for (int i = 0; i < currentNodes.size(); i++) {
    326                 if (currentNodes.get(i).getId() != historyNodes.get(i)) return false;
    327             }
    328             return true;
     360            return hasEqualSemanticAttributesWay((HistoryWay) history, (Way) current);
    329361        case MULTIPOLYGON:
    330362        case RELATION:
    331             List<org.openstreetmap.josm.data.osm.RelationMember> currentMembers =
    332                 ((Relation) current).getMembers();
    333             List<RelationMemberData> historyMembers = ((HistoryRelation) history).getMembers();
    334             if (currentMembers.size() != historyMembers.size()) return false;
    335             for (int i = 0; i < currentMembers.size(); i++) {
    336                 org.openstreetmap.josm.data.osm.RelationMember currentMember =
     363            return hasEqualSemanticAttributesRelation((HistoryRelation) history, (Relation) current);
     364        default: throw new AssertionError();
     365        }
     366    }
     367
     368    /**
     369     * Check if two nodes with the same tags are otherwise semantically similar
     370     * @param nds The dataset with downloaded data from OSM (see {@link #nds})
     371     * @param history The node history
     372     * @param current The current node
     373     * @return {@code true} if they are semantically similar
     374     */
     375    private static boolean hasEqualSemanticAttributesNode(DataSet nds, HistoryNode history, Node current) {
     376        LatLon currentCoor = current.getCoor();
     377        LatLon historyCoor = history.getCoords();
     378        if (Objects.equals(currentCoor, historyCoor))
     379            return true;
     380        // Handle case where a deleted note has been restored to avoid false conflicts (fix #josm8660)
     381        if (currentCoor != null && historyCoor == null) {
     382            LatLon previousCoor = ((Node) nds.getPrimitiveById(history.getPrimitiveId())).getCoor();
     383            return previousCoor != null && previousCoor.equals(currentCoor);
     384        }
     385        return false;
     386    }
     387
     388    /**
     389     * Check if two ways with the same tags are otherwise semantically similar
     390     * @param history The way history
     391     * @param current The current way
     392     * @return {@code true} if they are semantically similar
     393     */
     394    private static boolean hasEqualSemanticAttributesWay(HistoryWay history, Way current) {
     395        List<Node> currentNodes = current.getNodes();
     396        List<Long> historyNodes = history.getNodes();
     397        if (currentNodes.size() != historyNodes.size()) return false;
     398        for (int i = 0; i < currentNodes.size(); i++) {
     399            if (currentNodes.get(i).getId() != historyNodes.get(i)) return false;
     400        }
     401        return true;
     402    }
     403
     404    /**
     405     * Check if two relations with the same tags are otherwise semantically similar
     406     * @param history The relation history
     407     * @param current The current relation
     408     * @return {@code true} if they are semantically similar
     409     */
     410    private static boolean hasEqualSemanticAttributesRelation(HistoryRelation history, Relation current) {
     411        List<org.openstreetmap.josm.data.osm.RelationMember> currentMembers = current.getMembers();
     412        List<RelationMemberData> historyMembers = history.getMembers();
     413        if (currentMembers.size() != historyMembers.size()) return false;
     414        for (int i = 0; i < currentMembers.size(); i++) {
     415            org.openstreetmap.josm.data.osm.RelationMember currentMember =
    337416                    currentMembers.get(i);
    338                 RelationMemberData historyMember = historyMembers.get(i);
    339                 if (!currentMember.getRole().equals(historyMember.getRole())) return false;
    340                 if (!currentMember.getMember().getPrimitiveId().equals(new SimplePrimitiveId(
    341                         historyMember.getMemberId(), historyMember.getMemberType()))) return false;
    342             }
    343             return true;
    344         default: throw new AssertionError();
    345         }
     417            RelationMemberData historyMember = historyMembers.get(i);
     418            if (!currentMember.getRole().equals(historyMember.getRole())) return false;
     419            if (!currentMember.getMember().getPrimitiveId().equals(new SimplePrimitiveId(
     420                    historyMember.getMemberId(), historyMember.getMemberType()))) return false;
     421        }
     422        return true;
    346423    }
    347424
     
    386463        }
    387464
    388         // Check objects versions
     465        checkObjectVersions(cmds, conflicted, toDelete);
     466        checkForDeletedReferrers(cmds, conflicted, toDelete);
     467        return cmds;
     468    }
     469
     470    /**
     471     * Check objects versions
     472     * @param cmds The command list to add to
     473     * @param conflicted The primitives with conflicts
     474     * @param toDelete The primitives that will be deleted
     475     */
     476    private void checkObjectVersions(List<Command> cmds, HashSet<OsmPrimitive> conflicted, HashSet<OsmPrimitive> toDelete) {
    389477        for (Iterator<ChangesetDataSetEntry> it = cds.iterator(); it.hasNext();) {
    390478            ChangesetDataSetEntry entry = it.next();
    391             if (!checkOsmChangeEntry(entry)) continue;
    392             if (entry.getModificationType() == ChangesetModificationType.DELETED
    393                     && revertType == RevertType.SELECTION_WITH_UNDELETE) {
    394                 // see #22520: missing merge target when object is first created and then
    395                 // deleted in the same changeset
    396                 ChangesetDataSetEntry first = cds.getFirstEntry(entry.getPrimitive().getPrimitiveId());
    397                 if (first.getModificationType() == ChangesetModificationType.CREATED)
    398                     continue;
    399             }
    400             HistoryOsmPrimitive hp = entry.getPrimitive();
    401             OsmPrimitive dp = ds.getPrimitiveById(hp.getPrimitiveId());
    402             if (dp == null || dp.isIncomplete()) {
    403                 throw new IllegalStateException(addChangesetIdPrefix(tr("Missing merge target for {0}", hp.getPrimitiveId())));
    404             }
    405 
    406             if (hp.getVersion() != dp.getVersion()
    407                     && (hp.isVisible() || dp.isVisible()) &&
    408                     /* Don't create conflict if changeset object and dataset object
    409                      * has same semantic attributes (but different versions) */
    410                     !hasEqualSemanticAttributes(dp, hp)
    411                     /* Don't create conflict if the object has to be deleted but has already been deleted */
    412                     && !(toDelete.contains(dp) && dp.isDeleted())) {
    413                 cmds.add(new ConflictAddCommand(layer.data, createConflict(dp,
    414                         entry.getModificationType() == ChangesetModificationType.CREATED)));
    415                 conflicted.add(dp);
    416             }
    417         }
    418 
    419         /* Check referrers for deleted objects: if object is referred by another object that
    420          * isn't going to be deleted or modified, create a conflict.
    421          */
     479            if (checkOsmChangeEntry(entry) && checkModificationType(cds, entry, revertType)) {
     480                HistoryOsmPrimitive hp = entry.getPrimitive();
     481                OsmPrimitive dp = ds.getPrimitiveById(hp.getPrimitiveId());
     482                if (dp == null || dp.isIncomplete()) {
     483                    throw new IllegalStateException(addChangesetIdPrefix(tr("Missing merge target for {0}", hp.getPrimitiveId())));
     484                }
     485
     486                if (checkObjectVersionsNotSemanticallySame(toDelete, hp, dp)) {
     487                    cmds.add(new ConflictAddCommand(layer.data, createConflict(dp,
     488                            entry.getModificationType() == ChangesetModificationType.CREATED)));
     489                    conflicted.add(dp);
     490                }
     491            }
     492        }
     493    }
     494
     495    /**
     496     * Check that the modification type is something that we are looking at
     497     * @param cds {@link #cds} (current changeset data)
     498     * @param entry The entry in the changeset data
     499     * @param revertType The type of revert we are doing
     500     * @return {@code true} if the entry is something we are interested in for this revert
     501     */
     502    private static boolean checkModificationType(ChangesetDataSet cds, ChangesetDataSetEntry entry, RevertType revertType) {
     503        if (entry.getModificationType() == ChangesetModificationType.DELETED
     504                && revertType == RevertType.SELECTION_WITH_UNDELETE) {
     505            // see #22520: missing merge target when object is first created and then
     506            // deleted in the same changeset
     507            ChangesetDataSetEntry first = cds.getFirstEntry(entry.getPrimitive().getPrimitiveId());
     508            return first.getModificationType() != ChangesetModificationType.CREATED;
     509        }
     510        return true;
     511    }
     512
     513    /**
     514     * Check that versions are not the same prior to creating a conflict
     515     * @param toDelete The deleted objects
     516     * @param hp The history primitive
     517     * @param dp The current primitive
     518     * @return {@code true} if the objects are not semantically the same
     519     */
     520    private boolean checkObjectVersionsNotSemanticallySame(HashSet<OsmPrimitive> toDelete, HistoryOsmPrimitive hp, OsmPrimitive dp) {
     521        return hp.getVersion() != dp.getVersion()
     522                && (hp.isVisible() || dp.isVisible()) &&
     523                /* Don't create conflict if changeset object and dataset object
     524                 * has same semantic attributes (but different versions) */
     525                !hasEqualSemanticAttributes(dp, hp)
     526                /* Don't create conflict if the object has to be deleted but has already been deleted */
     527                && !(toDelete.contains(dp) && dp.isDeleted());
     528    }
     529
     530    /**
     531     * Check referrers for deleted objects: if object is referred by another object that
     532     * isn't going to be deleted or modified, create a conflict.
     533     * @param cmds The command list to add to
     534     * @param conflicted The primitives with conflicts
     535     * @param toDelete The primitives that will be deleted
     536     */
     537    private void checkForDeletedReferrers(List<Command> cmds, HashSet<OsmPrimitive> conflicted, HashSet<OsmPrimitive> toDelete) {
    422538        List<OsmPrimitive> delSorted = toDelete.stream()
    423539                .filter(p -> !p.isDeleted())
     
    429545            for (int i = 0; i < delSorted.size() && !restartNeeded; i++) {
    430546                OsmPrimitive p = delSorted.get(i);
    431                 for (OsmPrimitive referrer : p.getReferrers()) {
    432                     if (toDelete.contains(referrer)) continue; // object is going to be deleted
    433                     if (nds.getPrimitiveById(referrer) != null)
    434                         continue; /* object is going to be modified so it cannot refer to
    435                          * objects created in changeset to be reverted
    436                          */
    437                     if (conflicted.add(p)) {
    438                         cmds.add(new ConflictAddCommand(layer.data, createConflict(p, true)));
    439                         if (p instanceof Relation) {
    440                             // handle possible special case with nested relations
    441                             for (int j = 0; j < i; j++) {
    442                                 if (delSorted.get(j).getReferrers().contains(p)) {
    443                                     // we have to create a conflict for a previously processed relation
    444                                     restartNeeded = true;
    445                                     break;
    446                                 }
    447                             }
    448                         }
    449                     }
    450                     toDelete.remove(p);
    451                     break;
    452                 }
     547                restartNeeded = checkForDeletedReferrersPrimitive(cmds, conflicted, toDelete, delSorted, p, i);
    453548            }
    454549        } while (restartNeeded);
     
    458553            cmds.add(new DeleteCommand(delSorted));
    459554        }
    460         return cmds;
    461     }
    462 
     555    }
     556
     557    /**
     558     *
     559     * @param cmds The command list to add to
     560     * @param conflicted The primitives with conflicts
     561     * @param toDelete The primitives that will be deleted
     562     * @param delSorted The list of sorted deleted objects we need to check against
     563     * @param p The primitive to check
     564     * @param i The current index in {@code delSorted}
     565     * @return {@code true} if we need to restart processing
     566     */
     567    private boolean checkForDeletedReferrersPrimitive(List<Command> cmds, HashSet<OsmPrimitive> conflicted,
     568                                                      HashSet<OsmPrimitive> toDelete, List<OsmPrimitive> delSorted,
     569                                                      OsmPrimitive p, int i) {
     570        for (OsmPrimitive referrer : p.getReferrers()) {
     571            if (toDelete.contains(referrer) || // object is going to be deleted
     572                    nds.getPrimitiveById(referrer) != null)
     573                continue; /* object is going to be modified so it cannot refer to
     574                 * objects created in changeset to be reverted
     575                 */
     576            if (conflicted.add(p)) {
     577                cmds.add(new ConflictAddCommand(layer.data, createConflict(p, true)));
     578                if (p instanceof Relation) {
     579                    // handle possible special case with nested relations
     580                    for (int j = 0; j < i; j++) {
     581                        if (delSorted.get(j).getReferrers().contains(p)) {
     582                            // we have to create a conflict for a previously processed relation
     583                            return true;
     584                        }
     585                    }
     586                }
     587            }
     588            toDelete.remove(p);
     589            return false;
     590        }
     591        return false;
     592    }
     593
     594    /**
     595     * Check if there are missing objects
     596     * @return {@code true} if we need to handle missing objects
     597     */
    463598    public boolean hasMissingObjects() {
    464599        return !missing.isEmpty();
    465600    }
    466601
     602    /**
     603     * Get coordinates for nodes that have no coordinates
     604     * @param progressMonitor The monitor to update our progress with
     605     * @throws OsmTransferException If we have an issue getting data from the API
     606     */
    467607    public void fixNodesWithoutCoordinates(ProgressMonitor progressMonitor) throws OsmTransferException {
    468608        Collection<Node> nodes = new ArrayList<>(nds.getNodes());
  • applications/editors/josm/plugins/reverter/src/reverter/RevertChangesetAction.java

    r35579 r36318  
    22package reverter;
    33
     4import static org.openstreetmap.josm.tools.I18n.marktr;
    45import static org.openstreetmap.josm.tools.I18n.tr;
    56
     
    1415import reverter.ChangesetReverter.RevertType;
    1516
     17/**
     18 * An action for reverting changesets
     19 */
    1620public class RevertChangesetAction extends JosmAction {
     21    private static final String REVERT_CHANGESET = marktr("Revert changeset");
    1722
     23    /**
     24     * Create a new action for reverting changesets
     25     */
    1826    public RevertChangesetAction() {
    19         super(tr("Revert changeset"), "revert-changeset", tr("Revert changeset"),
    20             Shortcut.registerShortcut("tool:revert", tr("Data: {0}", tr("Revert changeset")), KeyEvent.VK_T, Shortcut.CTRL_SHIFT),
     27        super(tr(REVERT_CHANGESET), "revert-changeset", tr(REVERT_CHANGESET),
     28            Shortcut.registerShortcut("tool:revert", tr("Data: {0}", tr(REVERT_CHANGESET)), KeyEvent.VK_T, Shortcut.CTRL_SHIFT),
    2129                true, false);
    2230    }
  • applications/editors/josm/plugins/reverter/src/reverter/RevertChangesetTask.java

    r36230 r36318  
    99import java.util.Collections;
    1010import java.util.List;
    11 import java.util.concurrent.Callable;
    1211import java.util.stream.Collectors;
    1312
     
    3029import reverter.ChangesetReverter.RevertType;
    3130
     31/**
     32 * The task for reverting changesets
     33 */
    3234public class RevertChangesetTask extends PleaseWaitRunnable {
    3335    private final Collection<Integer> changesetIds;
     
    4042    private int numberOfConflicts;
    4143
     44    /**
     45     * Create a new task for reverting a changeset with a default progress monitor and no new layer with user confirmation of the download
     46     * @param changesetId The changeset id to revert
     47     * @param revertType The type of revert to do
     48     */
    4249    public RevertChangesetTask(int changesetId, RevertType revertType) {
    4350        this(changesetId, revertType, false);
    4451    }
    4552
     53    /**
     54     * Create a new task for reverting a changeset with a default progress monitor and no new layer
     55     * @param changesetId The changeset id to revert
     56     * @param revertType The type of revert to do
     57     * @param autoConfirmDownload {@code true} if the user has already indicated that they want to download missing data
     58     */
    4659    public RevertChangesetTask(int changesetId, RevertType revertType, boolean autoConfirmDownload) {
    4760        this(changesetId, revertType, autoConfirmDownload, false);
    4861    }
    4962
     63    /**
     64     * Create a new task for reverting a changeset with a default progress monitor
     65     * @param changesetId The changeset id to revert
     66     * @param revertType The type of revert to do
     67            * @param autoConfirmDownload {@code true} if the user has already indicated that they want to download missing data
     68     * @param newLayer {@code true} if the user wants the reversion to be on a new layer
     69     */
    5070    public RevertChangesetTask(int changesetId, RevertType revertType, boolean autoConfirmDownload, boolean newLayer) {
    5171        this(Collections.singleton(changesetId), revertType, autoConfirmDownload, newLayer);
    5272    }
    5373
     74    /**
     75     * Create a new task for reverting a changeset with a default progress monitor
     76     * @param changesetIds The changeset ids to revert
     77     * @param revertType The type of revert to do
     78     * @param autoConfirmDownload {@code true} if the user has already indicated that they want to download missing data
     79     * @param newLayer {@code true} if the user wants the reversion to be on a new layer
     80     */
    5481    public RevertChangesetTask(Collection<Integer> changesetIds, RevertType revertType, boolean autoConfirmDownload, boolean newLayer) {
    5582        this(null, changesetIds, revertType, autoConfirmDownload, newLayer);
     
    6491     * @param newLayer {@code true} if the user wants the reversion to be on a new layer
    6592     */
    66     public RevertChangesetTask(ProgressMonitor progressMonitor, Collection<Integer> changesetIds, RevertType revertType, boolean autoConfirmDownload, boolean newLayer) {
     93    public RevertChangesetTask(ProgressMonitor progressMonitor, Collection<Integer> changesetIds, RevertType revertType,
     94                               boolean autoConfirmDownload, boolean newLayer) {
    6795        super(tr("Reverting..."), progressMonitor, false);
    6896        this.changesetIds = new ArrayList<>(changesetIds);
     
    77105        if (!rev.hasMissingObjects()) return true;
    78106        if (!downloadConfirmed) {
    79             final Integer selectedOption = GuiHelper.runInEDTAndWaitAndReturn(new Callable<Integer>() {
    80                 @Override
    81                 public Integer call() throws Exception {
    82                     return JOptionPane.showConfirmDialog(MainApplication.getMainFrame(),
    83                             tr("This changeset has objects that are not present in current dataset.\n" +
    84                                     "It is needed to download them before reverting. Do you want to continue?"),
    85                             tr("Confirm"), JOptionPane.YES_NO_OPTION);
    86                 }
    87             });
     107            final Integer selectedOption = GuiHelper.runInEDTAndWaitAndReturn(() -> JOptionPane.showConfirmDialog(MainApplication.getMainFrame(),
     108                    tr("This changeset has objects that are not present in current dataset.\n" +
     109                            "It is needed to download them before reverting. Do you want to continue?"),
     110                    tr("Confirm"), JOptionPane.YES_NO_OPTION));
    88111            downloadConfirmed = selectedOption != null && selectedOption == JOptionPane.YES_OPTION;
    89112            if (!downloadConfirmed) return false;
     
    142165            rev = new ChangesetReverter(changesetId, revertType, newLayer, oldDataSet, progressMonitor.createSubTaskMonitor(0, true));
    143166        } catch (final RevertRedactedChangesetException e) {
     167            Logging.debug(e);
    144168            GuiHelper.runInEDT(() -> new Notification(
    145169                    e.getMessage()+"<br>"+
     
    191215            return null;
    192216        }
    193         GuiHelper.runInEDT(() -> cmds.get(0).getAffectedDataSet().update(() -> {
     217        GuiHelper.runInEDT(() -> executeCommands(cmds));
     218        final String desc = getRevertDescription(revertType, changesetId);
     219        return new RevertChangesetCommand(desc, cmds);
     220    }
     221
     222    /**
     223     * Execute a list of commands
     224     * @param cmds The commands to execute
     225     */
     226    private void executeCommands(List<Command> cmds) {
     227        cmds.get(0).getAffectedDataSet().update(() -> {
    194228            for (Command c : cmds) {
    195229                if (c instanceof ConflictAddCommand) {
     
    198232                c.executeCommand();
    199233            }
    200         }));
    201         final String desc;
     234        });
     235    }
     236
     237    /**
     238     * Get the description to show the user for this reversion
     239     * @param revertType The type of revert
     240     * @param changesetId The changeset id
     241     * @return The string to show the user
     242     */
     243    private static String getRevertDescription(RevertType revertType, int changesetId) {
    202244        if (revertType == RevertType.FULL) {
    203             desc = tr("Revert changeset {0}", String.valueOf(changesetId));
     245            return tr("Revert changeset {0}", String.valueOf(changesetId));
    204246        } else {
    205             desc = tr("Partially revert changeset {0}", String.valueOf(changesetId));
    206         }
    207         return new RevertChangesetCommand(desc, cmds);
     247            return tr("Partially revert changeset {0}", String.valueOf(changesetId));
     248        }
    208249    }
    209250
Note: See TracChangeset for help on using the changeset viewer.