/**
   * Replies the list of {@link Command commands} needed to resolve specified conflicts, by
   * displaying if necessary a {@link CombinePrimitiveResolverDialog} to the user. This dialog will
   * allow the user to choose conflict resolution actions.
   *
   * <p>Non-expert users are informed first of the meaning of these operations, allowing them to
   * cancel.
   *
   * @param tagsOfPrimitives The tag collection of the primitives to be combined. Should generally
   *     be equal to {@code TagCollection.unionOfAllPrimitives(primitives)}
   * @param primitives The primitives to be combined
   * @param targetPrimitives The primitives the collection of primitives are merged or combined to.
   * @return The list of {@link Command commands} needed to apply resolution actions.
   * @throws UserCancelException If the user cancelled a dialog.
   */
  public static List<Command> launchIfNecessary(
      final TagCollection tagsOfPrimitives,
      final Collection<? extends OsmPrimitive> primitives,
      final Collection<? extends OsmPrimitive> targetPrimitives)
      throws UserCancelException {

    CheckParameterUtil.ensureParameterNotNull(tagsOfPrimitives, "tagsOfPrimitives");
    CheckParameterUtil.ensureParameterNotNull(primitives, "primitives");
    CheckParameterUtil.ensureParameterNotNull(targetPrimitives, "targetPrimitives");

    final TagCollection completeWayTags = new TagCollection(tagsOfPrimitives);
    TagConflictResolutionUtil.combineTigerTags(completeWayTags);
    TagConflictResolutionUtil.normalizeTagCollectionBeforeEditing(completeWayTags, primitives);
    final TagCollection tagsToEdit = new TagCollection(completeWayTags);
    TagConflictResolutionUtil.completeTagCollectionForEditing(tagsToEdit);

    final Set<Relation> parentRelations = OsmPrimitive.getParentRelations(primitives);

    // Show information dialogs about conflicts to non-experts
    if (!ExpertToggleAction.isExpert()) {
      // Tag conflicts
      if (!completeWayTags.isApplicableToPrimitive()) {
        informAboutTagConflicts(primitives, completeWayTags);
      }
      // Relation membership conflicts
      if (!parentRelations.isEmpty()) {
        informAboutRelationMembershipConflicts(primitives, parentRelations);
      }
    }

    List<Command> cmds = new LinkedList<>();

    if (!GraphicsEnvironment.isHeadless()) {
      // Build conflict resolution dialog
      final CombinePrimitiveResolverDialog dialog = CombinePrimitiveResolverDialog.getInstance();

      dialog
          .getTagConflictResolverModel()
          .populate(tagsToEdit, completeWayTags.getKeysWithMultipleValues());
      dialog.getRelationMemberConflictResolverModel().populate(parentRelations, primitives);
      dialog.prepareDefaultDecisions();

      // Ensure a proper title is displayed instead of a previous target (fix #7925)
      if (targetPrimitives.size() == 1) {
        dialog.setTargetPrimitive(targetPrimitives.iterator().next());
      } else {
        dialog.setTargetPrimitive(null);
      }

      // Resolve tag conflicts if necessary
      if (!dialog.isResolvedCompletely()) {
        dialog.setVisible(true);
        if (!dialog.isApplied()) {
          throw new UserCancelException();
        }
      }
      for (OsmPrimitive i : targetPrimitives) {
        dialog.setTargetPrimitive(i);
        cmds.addAll(dialog.buildResolutionCommands());
      }
    }
    return cmds;
  }