Subject: [PATCH] #23555: Replace geometry update
---
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
diff --git a/core/src/org/openstreetmap/josm/actions/MergeNodesAction.java b/core/src/org/openstreetmap/josm/actions/MergeNodesAction.java
|
a
|
b
|
|
| 293 | 293 | * @since 12689 |
| 294 | 294 | */ |
| 295 | 295 | public static Command mergeNodes(Collection<Node> nodes, Node targetLocationNode) { |
| | 296 | return mergeNodes(nodes, targetLocationNode, CombinePrimitiveResolverDialog.Strategy.ASK); |
| | 297 | } |
| | 298 | |
| | 299 | /** |
| | 300 | * Merges the nodes in {@code nodes} at the specified node's location. |
| | 301 | * |
| | 302 | * @param nodes the collection of nodes. Ignored if null. |
| | 303 | * @param targetLocationNode this node's location will be used for the targetNode. |
| | 304 | * @param strategy The strategy to use for tag conflicts |
| | 305 | * @return The command necessary to run in order to perform action, or {@code null} if there is nothing to do |
| | 306 | * @throws IllegalArgumentException if {@code layer} is null |
| | 307 | * @since xxx |
| | 308 | */ |
| | 309 | public static Command mergeNodes(Collection<Node> nodes, Node targetLocationNode, CombinePrimitiveResolverDialog.Strategy strategy) { |
| 296 | 310 | if (nodes == null) { |
| 297 | 311 | return null; |
| 298 | 312 | } |
| … |
… |
|
| 302 | 316 | if (targetNode == null) { |
| 303 | 317 | return null; |
| 304 | 318 | } |
| 305 | | return mergeNodes(nodes, targetNode, targetLocationNode); |
| | 319 | return mergeNodes(nodes, targetNode, targetLocationNode, strategy); |
| 306 | 320 | } |
| 307 | 321 | |
| 308 | 322 | /** |
| … |
… |
|
| 315 | 329 | * @throws IllegalArgumentException if layer is null |
| 316 | 330 | */ |
| 317 | 331 | public static Command mergeNodes(Collection<Node> nodes, Node targetNode, Node targetLocationNode) { |
| | 332 | return mergeNodes(nodes, targetNode, targetLocationNode, CombinePrimitiveResolverDialog.Strategy.ASK); |
| | 333 | } |
| | 334 | |
| | 335 | /** |
| | 336 | * Merges the nodes in <code>nodes</code> onto one of the nodes. |
| | 337 | * |
| | 338 | * @param nodes the collection of nodes. Ignored if null. |
| | 339 | * @param targetNode the target node the collection of nodes is merged to. Must not be null. |
| | 340 | * @param targetLocationNode this node's location will be used for the targetNode. |
| | 341 | * @param strategy The strategy to use when there are tag conflicts |
| | 342 | * @return The command necessary to run in order to perform action, or {@code null} if there is nothing to do |
| | 343 | * @throws IllegalArgumentException if layer is null |
| | 344 | * @since xxx |
| | 345 | */ |
| | 346 | public static Command mergeNodes(Collection<Node> nodes, Node targetNode, Node targetLocationNode, |
| | 347 | CombinePrimitiveResolverDialog.Strategy strategy) { |
| 318 | 348 | CheckParameterUtil.ensureParameterNotNull(targetNode, "targetNode"); |
| 319 | 349 | if (nodes == null) { |
| 320 | 350 | return null; |
| … |
… |
|
| 346 | 376 | cmds.add(new ChangeCommand(targetNode, newTargetNode)); |
| 347 | 377 | } |
| 348 | 378 | } |
| 349 | | cmds.addAll(CombinePrimitiveResolverDialog.launchIfNecessary(nodeTags, nodes, Collections.singleton(targetNode))); |
| | 379 | cmds.addAll(CombinePrimitiveResolverDialog.launchIfNecessary(nodeTags, nodes, Collections.singleton(targetNode), strategy)); |
| 350 | 380 | if (!nodesToDelete.isEmpty()) { |
| 351 | 381 | cmds.add(new DeleteCommand(nodesToDelete)); |
| 352 | 382 | } |
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
diff --git a/core/src/org/openstreetmap/josm/gui/conflict/tags/CombinePrimitiveResolverDialog.java b/core/src/org/openstreetmap/josm/gui/conflict/tags/CombinePrimitiveResolverDialog.java
|
a
|
b
|
|
| 84 | 84 | */ |
| 85 | 85 | public class CombinePrimitiveResolverDialog extends JDialog { |
| 86 | 86 | |
| | 87 | /** |
| | 88 | * The strategy to use when combining tags |
| | 89 | */ |
| | 90 | public enum Strategy { |
| | 91 | /** Keep the tags from the target when there are conflicts */ |
| | 92 | KEEP_TARGET, |
| | 93 | /** Keep the tags from the source when there are conflicts */ |
| | 94 | KEEP_SOURCE, |
| | 95 | /** Keep the tags from both the source and the target when there are conflicts */ |
| | 96 | KEEP_BOTH, |
| | 97 | /** Keep all non-conflicting tags */ |
| | 98 | KEEP_NON_CONFLICTING, |
| | 99 | /** Ask if there are any conflicts, including when one objects has tags the other object does not */ |
| | 100 | ASK |
| | 101 | } |
| | 102 | |
| 87 | 103 | private AutoAdjustingSplitPane spTagConflictTypes; |
| 88 | 104 | private final TagConflictResolverModel modelTagConflictResolver; |
| 89 | 105 | protected TagConflictResolver pnlTagConflictResolver; |
| … |
… |
|
| 486 | 502 | final TagCollection tagsOfPrimitives, |
| 487 | 503 | final Collection<? extends OsmPrimitive> primitives, |
| 488 | 504 | final Collection<? extends OsmPrimitive> targetPrimitives) throws UserCancelException { |
| | 505 | return launchIfNecessary(tagsOfPrimitives, primitives, targetPrimitives, Strategy.ASK); |
| | 506 | } |
| 489 | 507 | |
| | 508 | /** |
| | 509 | * Replies the list of {@link Command commands} needed to resolve specified conflicts, |
| | 510 | * by displaying if necessary a {@link CombinePrimitiveResolverDialog} to the user. |
| | 511 | * This dialog will allow the user to choose conflict resolution actions. |
| | 512 | * <p> |
| | 513 | * Non-expert users are informed first of the meaning of these operations, allowing them to cancel. |
| | 514 | * |
| | 515 | * @param tagsOfPrimitives The tag collection of the primitives to be combined. |
| | 516 | * Should generally be equal to {@code TagCollection.unionOfAllPrimitives(primitives)} |
| | 517 | * @param primitives The primitives to be combined |
| | 518 | * @param targetPrimitives The primitives the collection of primitives are merged or combined to. |
| | 519 | * @pararm strategy The strategy to use when merging primitives |
| | 520 | * @return The list of {@link Command commands} needed to apply resolution actions. |
| | 521 | * @throws UserCancelException If the user cancelled a dialog. |
| | 522 | * @since xxx |
| | 523 | */ |
| | 524 | public static List<Command> launchIfNecessary( |
| | 525 | final TagCollection tagsOfPrimitives, |
| | 526 | final Collection<? extends OsmPrimitive> primitives, |
| | 527 | final Collection<? extends OsmPrimitive> targetPrimitives, |
| | 528 | Strategy strategy) throws UserCancelException { |
| 490 | 529 | CheckParameterUtil.ensureParameterNotNull(tagsOfPrimitives, "tagsOfPrimitives"); |
| 491 | 530 | CheckParameterUtil.ensureParameterNotNull(primitives, "primitives"); |
| 492 | 531 | CheckParameterUtil.ensureParameterNotNull(targetPrimitives, "targetPrimitives"); |
| … |
… |
|
| 518 | 557 | |
| 519 | 558 | tagModel.populate(tagsToEdit, completeWayTags.getKeysWithMultipleValues(), false); |
| 520 | 559 | relModel.populate(parentRelations, primitives, false); |
| 521 | | if (Config.getPref().getBoolean("combine-conflict-precise", true)) { |
| | 560 | if (Strategy.ASK == strategy && Config.getPref().getBoolean("combine-conflict-precise", true)) { |
| 522 | 561 | tagModel.prepareDefaultTagDecisions(getResolvableKeys(tagsOfPrimitives.getKeys(), primitives)); |
| 523 | 562 | } else { |
| 524 | 563 | tagModel.prepareDefaultTagDecisions(false); |
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
diff --git a/plugins/utilsplugin2/src/org/openstreetmap/josm/plugins/utilsplugin2/replacegeometry/ReplaceGeometryUtils.java b/plugins/utilsplugin2/src/org/openstreetmap/josm/plugins/utilsplugin2/replacegeometry/ReplaceGeometryUtils.java
|
a
|
b
|
|
| 81 | 81 | * @return (in case of success) a command to update the geometry of fist object and remove the other |
| 82 | 82 | */ |
| 83 | 83 | public static ReplaceGeometryCommand buildReplaceCommand(OsmPrimitive subjectObject, OsmPrimitive referenceSubject) { |
| | 84 | return buildReplaceCommand(subjectObject, referenceSubject, CombinePrimitiveResolverDialog.Strategy.ASK); |
| | 85 | } |
| | 86 | |
| | 87 | /** |
| | 88 | * Replace subjectObject geometry with referenceObject geometry and merge tags |
| | 89 | * and relation memberships. |
| | 90 | * @param subjectObject object to modify |
| | 91 | * @param referenceSubject object that gives new geometry and is removed |
| | 92 | * @param strategy The strategy to use when resolving conflicts |
| | 93 | * @return (in case of success) a command to update the geometry of fist object and remove the other |
| | 94 | */ |
| | 95 | public static ReplaceGeometryCommand buildReplaceCommand(OsmPrimitive subjectObject, OsmPrimitive referenceSubject, |
| | 96 | CombinePrimitiveResolverDialog.Strategy strategy) { |
| 84 | 97 | if (subjectObject instanceof Node && referenceSubject instanceof Node) { |
| 85 | | return buildReplaceNodeCommand((Node) subjectObject, (Node) referenceSubject); |
| | 98 | return buildReplaceNodeCommand((Node) subjectObject, (Node) referenceSubject, strategy); |
| 86 | 99 | } else if (subjectObject instanceof Way && referenceSubject instanceof Way) { |
| 87 | | return buildReplaceWayCommand((Way) subjectObject, (Way) referenceSubject); |
| | 100 | return buildReplaceWayCommand((Way) subjectObject, (Way) referenceSubject, strategy); |
| 88 | 101 | } else if (subjectObject instanceof Node) { |
| 89 | | return buildUpgradeNodeCommand((Node) subjectObject, referenceSubject); |
| | 102 | return buildUpgradeNodeCommand((Node) subjectObject, referenceSubject, strategy); |
| 90 | 103 | } else if (referenceSubject instanceof Node) { |
| 91 | 104 | // TODO: fix this illogical reversal? |
| 92 | | return buildUpgradeNodeCommand((Node) referenceSubject, subjectObject); |
| | 105 | return buildUpgradeNodeCommand((Node) referenceSubject, subjectObject, strategy); |
| 93 | 106 | } else { |
| 94 | 107 | throw new IllegalArgumentException( |
| 95 | 108 | tr("This tool can only replace a node, upgrade a node to a way or a multipolygon, or replace a way with a way.")); |
| … |
… |
|
| 120 | 133 | * @return command to replace node or null if user cancelled |
| 121 | 134 | */ |
| 122 | 135 | public static ReplaceGeometryCommand buildReplaceNodeCommand(Node subjectNode, Node referenceNode) { |
| | 136 | return buildUpgradeNodeCommand(subjectNode, referenceNode, CombinePrimitiveResolverDialog.Strategy.ASK); |
| | 137 | } |
| | 138 | |
| | 139 | /** |
| | 140 | * Replace a node with another node (similar to MergeNodesAction) |
| | 141 | * @param subjectNode node to be replaced |
| | 142 | * @param referenceNode node with greater spatial quality |
| | 143 | * @param strategy The strategy to use when resolving conflicts |
| | 144 | * @return command to replace node or null if user cancelled |
| | 145 | */ |
| | 146 | public static ReplaceGeometryCommand buildReplaceNodeCommand(Node subjectNode, Node referenceNode, |
| | 147 | CombinePrimitiveResolverDialog.Strategy strategy) { |
| 123 | 148 | if (!subjectNode.getParentWays().isEmpty()) { |
| 124 | 149 | throw new ReplaceGeometryException(tr("Node belongs to way(s), cannot replace.")); |
| 125 | 150 | } |
| 126 | 151 | // FIXME: handle different layers |
| 127 | 152 | List<Command> commands = new ArrayList<>(); |
| 128 | 153 | Command c = MergeNodesAction.mergeNodes( |
| 129 | | Arrays.asList(subjectNode, referenceNode), referenceNode); |
| | 154 | Arrays.asList(subjectNode, referenceNode), referenceNode, strategy); |
| 130 | 155 | if (c == null) { |
| 131 | 156 | // User cancelled |
| 132 | 157 | return null; |
| … |
… |
|
| 146 | 171 | * @return command to replace |
| 147 | 172 | */ |
| 148 | 173 | public static ReplaceGeometryCommand buildUpgradeNodeCommand(Node subjectNode, OsmPrimitive referenceObject) { |
| | 174 | return buildUpgradeNodeCommand(subjectNode, referenceObject, CombinePrimitiveResolverDialog.Strategy.ASK); |
| | 175 | } |
| | 176 | |
| | 177 | /** |
| | 178 | * Upgrade a node to a way or multipolygon |
| | 179 | * |
| | 180 | * @param subjectNode node to be replaced |
| | 181 | * @param referenceObject object with greater spatial quality |
| | 182 | * @param strategy The strategy to use when resolving tag conflicts |
| | 183 | * @return command to replace |
| | 184 | */ |
| | 185 | public static ReplaceGeometryCommand buildUpgradeNodeCommand(Node subjectNode, OsmPrimitive referenceObject, |
| | 186 | CombinePrimitiveResolverDialog.Strategy strategy) { |
| 149 | 187 | if (!subjectNode.getParentWays().isEmpty()) { |
| 150 | 188 | throw new ReplaceGeometryException(tr("Node belongs to way(s), cannot replace.")); |
| 151 | 189 | } |
| 152 | 190 | |
| 153 | | if (referenceObject instanceof Relation && !((Relation) referenceObject).isMultipolygon()) { |
| | 191 | if (referenceObject instanceof Relation && !referenceObject.isMultipolygon()) { |
| 154 | 192 | throw new ReplaceGeometryException(tr("Relation is not a multipolygon, cannot be used as a replacement.")); |
| 155 | 193 | } |
| 156 | 194 | |
| … |
… |
|
| 180 | 218 | } |
| 181 | 219 | } |
| 182 | 220 | |
| 183 | | List<Command> commands = new ArrayList<>(); |
| | 221 | List<Command> commands; |
| 184 | 222 | AbstractMap<String, String> nodeTags = subjectNode.getKeys(); |
| 185 | 223 | |
| 186 | 224 | // merge tags |
| 187 | 225 | try { |
| 188 | | commands.addAll(getTagConflictResolutionCommands(subjectNode, referenceObject)); |
| | 226 | commands = new ArrayList<>(getTagConflictResolutionCommands(subjectNode, referenceObject, strategy)); |
| 189 | 227 | } catch (UserCancelException e) { |
| 190 | 228 | // user cancelled tag merge dialog |
| 191 | 229 | return null; |
| … |
… |
|
| 266 | 304 | * @return Command to replace geometry or null if user cancelled |
| 267 | 305 | */ |
| 268 | 306 | public static ReplaceGeometryCommand buildReplaceWayCommand(Way subjectWay, Way referenceWay) { |
| | 307 | return buildReplaceWayCommand(subjectWay, referenceWay, CombinePrimitiveResolverDialog.Strategy.ASK); |
| | 308 | } |
| 269 | 309 | |
| | 310 | /** |
| | 311 | * Replace geometry of subjectWay by that of referenceWay. Tries to keep the history of nodes. |
| | 312 | * @param subjectWay way to modify |
| | 313 | * @param referenceWay way to remove |
| | 314 | * @param strategy The strategy to use when resolving conflicts |
| | 315 | * @return Command to replace geometry or null if user cancelled |
| | 316 | */ |
| | 317 | public static ReplaceGeometryCommand buildReplaceWayCommand(Way subjectWay, Way referenceWay, |
| | 318 | CombinePrimitiveResolverDialog.Strategy strategy) { |
| 270 | 319 | Area a = MainApplication.getLayerManager().getEditDataSet().getDataSourceArea(); |
| 271 | 320 | if (!isInArea(subjectWay, a) || !isInArea(referenceWay, a)) { |
| 272 | 321 | throw new ReplaceGeometryException(tr("The ways must be entirely within the downloaded area.")); |
| … |
… |
|
| 281 | 330 | |
| 282 | 331 | // merge tags |
| 283 | 332 | try { |
| 284 | | commands.addAll(getTagConflictResolutionCommands(referenceWay, subjectWay)); |
| | 333 | commands.addAll(getTagConflictResolutionCommands(referenceWay, subjectWay, strategy)); |
| 285 | 334 | } catch (UserCancelException e) { |
| 286 | 335 | // user cancelled tag merge dialog |
| 287 | 336 | Logging.trace(e); |
| … |
… |
|
| 472 | 521 | * |
| 473 | 522 | * @param source object tags are merged from |
| 474 | 523 | * @param target object tags are merged to |
| | 524 | * @param strategy The strategy to use when resolving conflicts |
| 475 | 525 | * @return The list of {@link Command commands} needed to apply resolution actions. |
| 476 | 526 | * @throws UserCancelException If the user cancelled a dialog. |
| 477 | 527 | */ |
| 478 | | static List<Command> getTagConflictResolutionCommands(OsmPrimitive source, OsmPrimitive target) throws UserCancelException { |
| | 528 | static List<Command> getTagConflictResolutionCommands(OsmPrimitive source, OsmPrimitive target, |
| | 529 | CombinePrimitiveResolverDialog.Strategy strategy) throws UserCancelException { |
| 479 | 530 | Collection<OsmPrimitive> primitives = Arrays.asList(source, target); |
| 480 | 531 | // launch a conflict resolution dialog, if necessary |
| 481 | 532 | return CombinePrimitiveResolverDialog.launchIfNecessary( |
| 482 | | TagCollection.unionOfAllPrimitives(primitives), primitives, Collections.singleton(target)); |
| | 533 | TagCollection.unionOfAllPrimitives(primitives), primitives, Collections.singleton(target), strategy); |
| 483 | 534 | } |
| 484 | 535 | |
| 485 | 536 | /** |