/**
   * Replies the list of {@link Command commands} needed to apply resolution choices.
   *
   * @return The list of {@link Command commands} needed to apply resolution choices.
   */
  public List<Command> buildResolutionCommands() {
    List<Command> cmds = new LinkedList<>();

    TagCollection allResolutions = getTagConflictResolverModel().getAllResolutions();
    if (!allResolutions.isEmpty()) {
      cmds.addAll(buildTagChangeCommand(targetPrimitive, allResolutions));
    }
    for (String p : OsmPrimitive.getDiscardableKeys()) {
      if (targetPrimitive.get(p) != null) {
        cmds.add(new ChangePropertyCommand(targetPrimitive, p, null));
      }
    }

    if (getRelationMemberConflictResolverModel().getNumDecisions() > 0) {
      cmds.addAll(
          getRelationMemberConflictResolverModel().buildResolutionCommands(targetPrimitive));
    }

    Command cmd =
        pnlRelationMemberConflictResolver.buildTagApplyCommands(
            getRelationMemberConflictResolverModel().getModifiedRelations(targetPrimitive));
    if (cmd != null) {
      cmds.add(cmd);
    }
    return cmds;
  }
 /**
  * Initializes the conflict resolver for a specific type of primitives
  *
  * @param type the type of primitives
  * @param tc the tags belonging to this type of primitives
  * @param targetStatistics histogram of paste targets, number of primitives of each type in the
  *     paste target
  */
 protected void initResolver(
     OsmPrimitiveType type, TagCollection tc, Map<OsmPrimitiveType, Integer> targetStatistics) {
   resolvers.get(type).getModel().populate(tc, tc.getKeysWithMultipleValues());
   resolvers.get(type).getModel().prepareDefaultTagDecisions();
   if (!tc.isEmpty() && targetStatistics.get(type) != null && targetStatistics.get(type) > 0) {
     tpResolvers.add(PANE_TITLES.get(type), resolvers.get(type));
   }
 }
  /**
   * Populate the tag conflict resolver with tags for each type of primitives
   *
   * @param tagsForNodes the tags belonging to nodes in the paste source
   * @param tagsForWays the tags belonging to way in the paste source
   * @param tagsForRelations the tags belonging to relations in the paste source
   * @param sourceStatistics histogram of tag source, number of primitives of each type in the
   *     source
   * @param targetStatistics histogram of paste targets, number of primitives of each type in the
   *     paste target
   */
  public void populate(
      TagCollection tagsForNodes,
      TagCollection tagsForWays,
      TagCollection tagsForRelations,
      Map<OsmPrimitiveType, Integer> sourceStatistics,
      Map<OsmPrimitiveType, Integer> targetStatistics) {
    tagsForNodes = (tagsForNodes == null) ? new TagCollection() : tagsForNodes;
    tagsForWays = (tagsForWays == null) ? new TagCollection() : tagsForWays;
    tagsForRelations = (tagsForRelations == null) ? new TagCollection() : tagsForRelations;
    if (tagsForNodes.isEmpty() && tagsForWays.isEmpty() && tagsForRelations.isEmpty()) {
      populate(null, null, null);
      return;
    }
    tpResolvers.removeAll();
    initResolver(OsmPrimitiveType.NODE, tagsForNodes, targetStatistics);
    initResolver(OsmPrimitiveType.WAY, tagsForWays, targetStatistics);
    initResolver(OsmPrimitiveType.RELATION, tagsForRelations, targetStatistics);

    pnlTagResolver.removeAll();
    pnlTagResolver.add(tpResolvers, BorderLayout.CENTER);
    mode = Mode.RESOLVING_TYPED_TAGCOLLECTIONS;
    validate();
    statisticsModel.reset();
    if (!tagsForNodes.isEmpty()) {
      StatisticsInfo info = new StatisticsInfo();
      info.numTags = tagsForNodes.getKeys().size();
      int numTargets =
          targetStatistics.get(OsmPrimitiveType.NODE) == null
              ? 0
              : targetStatistics.get(OsmPrimitiveType.NODE);
      if (numTargets > 0) {
        info.sourceInfo.put(OsmPrimitiveType.NODE, sourceStatistics.get(OsmPrimitiveType.NODE));
        info.targetInfo.put(OsmPrimitiveType.NODE, numTargets);
        statisticsModel.append(info);
      }
    }
    if (!tagsForWays.isEmpty()) {
      StatisticsInfo info = new StatisticsInfo();
      info.numTags = tagsForWays.getKeys().size();
      int numTargets =
          targetStatistics.get(OsmPrimitiveType.WAY) == null
              ? 0
              : targetStatistics.get(OsmPrimitiveType.WAY);
      if (numTargets > 0) {
        info.sourceInfo.put(OsmPrimitiveType.WAY, sourceStatistics.get(OsmPrimitiveType.WAY));
        info.targetInfo.put(OsmPrimitiveType.WAY, numTargets);
        statisticsModel.append(info);
      }
    }
    if (!tagsForRelations.isEmpty()) {
      StatisticsInfo info = new StatisticsInfo();
      info.numTags = tagsForRelations.getKeys().size();
      int numTargets =
          targetStatistics.get(OsmPrimitiveType.RELATION) == null
              ? 0
              : targetStatistics.get(OsmPrimitiveType.RELATION);
      if (numTargets > 0) {
        info.sourceInfo.put(
            OsmPrimitiveType.RELATION, sourceStatistics.get(OsmPrimitiveType.RELATION));
        info.targetInfo.put(OsmPrimitiveType.RELATION, numTargets);
        statisticsModel.append(info);
      }
    }

    for (int i = 0; i < getNumResolverTabs(); i++) {
      if (!getResolver(i).getModel().isResolvedCompletely()) {
        tpResolvers.setSelectedIndex(i);
        break;
      }
    }
  }