Esempio n. 1
0
  /**
   * 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);
  }