Ignore:
Timestamp:
2017-08-28T18:48:58+02:00 (4 years ago)
Author:
Don-vip
Message:

see #15182 - refactor PurgeAction/PurgeCommand to avoid unneeded dependence on action

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/PurgeCommand.java

    r12672 r12688  
    1616import javax.swing.Icon;
    1717
     18import org.openstreetmap.josm.Main;
    1819import org.openstreetmap.josm.data.conflict.Conflict;
    1920import org.openstreetmap.josm.data.conflict.ConflictCollection;
     
    2627import org.openstreetmap.josm.data.osm.Relation;
    2728import org.openstreetmap.josm.data.osm.RelationData;
     29import org.openstreetmap.josm.data.osm.RelationMember;
    2830import org.openstreetmap.josm.data.osm.Storage;
    2931import org.openstreetmap.josm.data.osm.Way;
     
    309311                Objects.equals(purgedConflicts, that.purgedConflicts);
    310312    }
     313
     314    /**
     315     * Creates a new {@code PurgeCommand} to purge selected OSM primitives.
     316     * @param layer optional osm data layer, can be null
     317     * @param sel selected OSM primitives
     318     * @param toPurgeAdditionally optional list that will be filled with primitives to be purged that have not been in the selection
     319     * @return command to purge selected OSM primitives
     320     * @since 12688
     321     */
     322    public static PurgeCommand build(OsmDataLayer layer, Collection<OsmPrimitive> sel, List<OsmPrimitive> toPurgeAdditionally) {
     323        Set<OsmPrimitive> toPurge = new HashSet<>(sel);
     324        // finally, contains all objects that are purged
     325        Set<OsmPrimitive> toPurgeChecked = new HashSet<>();
     326
     327        // Add referrer, unless the object to purge is not new and the parent is a relation
     328        Set<OsmPrimitive> toPurgeRecursive = new HashSet<>();
     329        while (!toPurge.isEmpty()) {
     330
     331            for (OsmPrimitive osm: toPurge) {
     332                for (OsmPrimitive parent: osm.getReferrers()) {
     333                    if (toPurge.contains(parent) || toPurgeChecked.contains(parent) || toPurgeRecursive.contains(parent)) {
     334                        continue;
     335                    }
     336                    if (parent instanceof Way || (parent instanceof Relation && osm.isNew())) {
     337                        if (toPurgeAdditionally != null) {
     338                            toPurgeAdditionally.add(parent);
     339                        }
     340                        toPurgeRecursive.add(parent);
     341                    }
     342                }
     343                toPurgeChecked.add(osm);
     344            }
     345            toPurge = toPurgeRecursive;
     346            toPurgeRecursive = new HashSet<>();
     347        }
     348
     349        // Subset of toPurgeChecked. Marks primitives that remain in the dataset, but incomplete.
     350        Set<OsmPrimitive> makeIncomplete = new HashSet<>();
     351
     352        // Find the objects that will be incomplete after purging.
     353        // At this point, all parents of new to-be-purged primitives are
     354        // also to-be-purged and
     355        // all parents of not-new to-be-purged primitives are either
     356        // to-be-purged or of type relation.
     357        TOP:
     358            for (OsmPrimitive child : toPurgeChecked) {
     359                if (child.isNew()) {
     360                    continue;
     361                }
     362                for (OsmPrimitive parent : child.getReferrers()) {
     363                    if (parent instanceof Relation && !toPurgeChecked.contains(parent)) {
     364                        makeIncomplete.add(child);
     365                        continue TOP;
     366                    }
     367                }
     368            }
     369
     370        // Add untagged way nodes. Do not add nodes that have other referrers not yet to-be-purged.
     371        if (Main.pref.getBoolean("purge.add_untagged_waynodes", true)) {
     372            Set<OsmPrimitive> wayNodes = new HashSet<>();
     373            for (OsmPrimitive osm : toPurgeChecked) {
     374                if (osm instanceof Way) {
     375                    Way w = (Way) osm;
     376                    NODE:
     377                        for (Node n : w.getNodes()) {
     378                            if (n.isTagged() || toPurgeChecked.contains(n)) {
     379                                continue;
     380                            }
     381                            for (OsmPrimitive ref : n.getReferrers()) {
     382                                if (ref != w && !toPurgeChecked.contains(ref)) {
     383                                    continue NODE;
     384                                }
     385                            }
     386                            wayNodes.add(n);
     387                        }
     388                }
     389            }
     390            toPurgeChecked.addAll(wayNodes);
     391            if (toPurgeAdditionally != null) {
     392                toPurgeAdditionally.addAll(wayNodes);
     393            }
     394        }
     395
     396        if (Main.pref.getBoolean("purge.add_relations_with_only_incomplete_members", true)) {
     397            Set<Relation> relSet = new HashSet<>();
     398            for (OsmPrimitive osm : toPurgeChecked) {
     399                for (OsmPrimitive parent : osm.getReferrers()) {
     400                    if (parent instanceof Relation
     401                            && !(toPurgeChecked.contains(parent))
     402                            && hasOnlyIncompleteMembers((Relation) parent, toPurgeChecked, relSet)) {
     403                        relSet.add((Relation) parent);
     404                    }
     405                }
     406            }
     407
     408            // Add higher level relations (list gets extended while looping over it)
     409            List<Relation> relLst = new ArrayList<>(relSet);
     410            for (int i = 0; i < relLst.size(); ++i) { // foreach loop not applicable since list gets extended while looping over it
     411                for (OsmPrimitive parent : relLst.get(i).getReferrers()) {
     412                    if (!(toPurgeChecked.contains(parent))
     413                            && hasOnlyIncompleteMembers((Relation) parent, toPurgeChecked, relLst)) {
     414                        relLst.add((Relation) parent);
     415                    }
     416                }
     417            }
     418            relSet = new HashSet<>(relLst);
     419            toPurgeChecked.addAll(relSet);
     420            if (toPurgeAdditionally != null) {
     421                toPurgeAdditionally.addAll(relSet);
     422            }
     423        }
     424
     425        return layer != null ? new PurgeCommand(layer, toPurgeChecked, makeIncomplete)
     426                : new PurgeCommand(toPurgeChecked.iterator().next().getDataSet(), toPurgeChecked, makeIncomplete);
     427    }
     428
     429    private static boolean hasOnlyIncompleteMembers(
     430            Relation r, Collection<OsmPrimitive> toPurge, Collection<? extends OsmPrimitive> moreToPurge) {
     431        for (RelationMember m : r.getMembers()) {
     432            if (!m.getMember().isIncomplete() && !toPurge.contains(m.getMember()) && !moreToPurge.contains(m.getMember()))
     433                return false;
     434        }
     435        return true;
     436    }
    311437}
Note: See TracChangeset for help on using the changeset viewer.