/** * Try to delete all given primitives. * * <p>If a node is used by a way, it's removed from that way. If a node or a way is used by a * relation, inform the user and do not delete. * * <p>If this would cause ways with less than 2 nodes to be created, delete these ways instead. If * they are part of a relation, inform the user and do not delete. * * @param layer the {@link OsmDataLayer} in whose context the primitives are deleted * @param selection the objects to delete. * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well * @param silent set to true if the user should not be bugged with additional questions * @return command a command to perform the deletions, or null if there is nothing to delete. */ public static Command delete( OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay, boolean silent) { if (selection == null || selection.isEmpty()) return null; // Diamond operator does not work with Java 9 here Set<OsmPrimitive> primitivesToDelete = new HashSet<OsmPrimitive>(selection); Collection<Relation> relationsToDelete = Utils.filteredCollection(primitivesToDelete, Relation.class); if (!relationsToDelete.isEmpty() && !silent && !confirmRelationDeletion(relationsToDelete)) return null; if (alsoDeleteNodesInWay) { // delete untagged nodes only referenced by primitives in primitivesToDelete, too Collection<Node> nodesToDelete = computeNodesToDelete(primitivesToDelete); primitivesToDelete.addAll(nodesToDelete); } if (!silent && !checkAndConfirmOutlyingDelete( primitivesToDelete, Utils.filteredCollection(primitivesToDelete, Way.class))) return null; Collection<Way> waysToBeChanged = new HashSet<>( OsmPrimitive.getFilteredSet(OsmPrimitive.getReferrer(primitivesToDelete), Way.class)); Collection<Command> cmds = new LinkedList<>(); for (Way w : waysToBeChanged) { Way wnew = new Way(w); wnew.removeNodes(OsmPrimitive.getFilteredSet(primitivesToDelete, Node.class)); if (wnew.getNodesCount() < 2) { primitivesToDelete.add(w); } else { cmds.add(new ChangeNodesCommand(w, wnew.getNodes())); } } // get a confirmation that the objects to delete can be removed from their parent relations // if (!silent) { Set<RelationToChildReference> references = RelationToChildReference.getRelationToChildReferences(primitivesToDelete); Iterator<RelationToChildReference> it = references.iterator(); while (it.hasNext()) { RelationToChildReference ref = it.next(); if (ref.getParent().isDeleted()) { it.remove(); } } if (!references.isEmpty()) { DeleteFromRelationConfirmationDialog dialog = DeleteFromRelationConfirmationDialog.getInstance(); dialog.getModel().populate(references); dialog.setVisible(true); if (dialog.isCanceled()) return null; } } // remove the objects from their parent relations // for (Relation cur : OsmPrimitive.getFilteredSet(OsmPrimitive.getReferrer(primitivesToDelete), Relation.class)) { Relation rel = new Relation(cur); rel.removeMembersFor(primitivesToDelete); cmds.add(new ChangeCommand(cur, rel)); } // build the delete command // if (!primitivesToDelete.isEmpty()) { cmds.add(new DeleteCommand(layer, primitivesToDelete)); } return new SequenceCommand(tr("Delete"), cmds); }