/** * Populates the conflict resolver with one tag collection * * @param tagsForAllPrimitives the tag collection * @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 tagsForAllPrimitives, Map<OsmPrimitiveType, Integer> sourceStatistics, Map<OsmPrimitiveType, Integer> targetStatistics) { mode = Mode.RESOLVING_ONE_TAGCOLLECTION_ONLY; tagsForAllPrimitives = tagsForAllPrimitives == null ? new TagCollection() : tagsForAllPrimitives; sourceStatistics = sourceStatistics == null ? new HashMap<>() : sourceStatistics; targetStatistics = targetStatistics == null ? new HashMap<>() : targetStatistics; // init the resolver // allPrimitivesResolver .getModel() .populate(tagsForAllPrimitives, tagsForAllPrimitives.getKeysWithMultipleValues()); allPrimitivesResolver.getModel().prepareDefaultTagDecisions(); // prepare the dialog with one tag resolver pnlTagResolver.removeAll(); pnlTagResolver.add(allPrimitivesResolver, BorderLayout.CENTER); statisticsModel.reset(); StatisticsInfo info = new StatisticsInfo(); info.numTags = tagsForAllPrimitives.getKeys().size(); info.sourceInfo.putAll(sourceStatistics); info.targetInfo.putAll(targetStatistics); statisticsModel.append(info); validate(); }
/** * 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)); } }
/** * Inform a non-expert user about what tag conflict resolution means. * * @param primitives The primitives to be combined * @param normalizedTags The normalized tag collection of the primitives to be combined * @throws UserCancelException If the user cancels the dialog. */ protected static void informAboutTagConflicts( final Collection<? extends OsmPrimitive> primitives, final TagCollection normalizedTags) throws UserCancelException { String conflicts = Utils.joinAsHtmlUnorderedList( Utils.transform( normalizedTags.getKeysWithMultipleValues(), new Function<String, String>() { @Override public String apply(String key) { return tr( "{0} ({1})", key, Utils.join( tr(", "), Utils.transform( normalizedTags.getValues(key), new Function<String, String>() { @Override public String apply(String x) { return x == null || x.isEmpty() ? tr("<i>missing</i>") : x; } }))); } })); String msg = /* for correct i18n of plural forms - see #9110 */ trn( "You are about to combine {0} objects, " + "but the following tags are used conflictingly:<br/>{1}" + "If these objects are combined, the resulting object may have unwanted tags.<br/>" + "If you want to continue, you are shown a dialog to fix the conflicting tags.<br/><br/>" + "Do you want to continue?", "You are about to combine {0} objects, " + "but the following tags are used conflictingly:<br/>{1}" + "If these objects are combined, the resulting object may have unwanted tags.<br/>" + "If you want to continue, you are shown a dialog to fix the conflicting tags.<br/><br/>" + "Do you want to continue?", primitives.size(), primitives.size(), conflicts); if (!ConditionalOptionPaneUtil.showConfirmationDialog( "combine_tags", Main.parent, "<html>" + msg + "</html>", tr("Combine confirmation"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_OPTION)) { throw new UserCancelException(); } }
/** * 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; }