Changeset 30782 in osm for applications/editors/josm


Ignore:
Timestamp:
2014-10-29T21:56:35+01:00 (10 years ago)
Author:
donvip
Message:

[josm-merge_overlap] fix sonar issues

Location:
applications/editors/josm/plugins/merge-overlap/src/mergeoverlap
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/MergeOverlapAction.java

    r30766 r30782  
    5050 * Merge overlapping part of ways.
    5151 */
    52 @SuppressWarnings("serial")
    5352public class MergeOverlapAction extends JosmAction {
    5453
    55         public MergeOverlapAction() {
    56                 super(tr("Merge overlap"), "merge_overlap",
    57                                 tr("Merge overlap of ways."),
    58                                 Shortcut.registerShortcut("tools:mergeoverlap",tr("Tool: {0}", tr("Merge overlap")), KeyEvent.VK_O,
    59                                 Shortcut.ALT_CTRL)
    60                                 , true);
    61         }
    62 
    63         Map<Way, List<Relation>> relations = new HashMap<>();
    64         Map<Way, Way> oldWays = new HashMap<>();
    65         Map<Relation, Relation> newRelations = new HashMap<>();
    66         Set<Way> deletes = new HashSet<>();
    67 
    68         /**
    69          * The action button has been clicked
    70          *
    71          * @param e
    72          *            Action Event
    73          */
     54    /**
     55     * Constructs a new {@code MergeOverlapAction}.
     56     */
     57    public MergeOverlapAction() {
     58        super(tr("Merge overlap"), "merge_overlap",
     59                tr("Merge overlap of ways."),
     60                Shortcut.registerShortcut("tools:mergeoverlap",tr("Tool: {0}", tr("Merge overlap")), KeyEvent.VK_O,
     61                Shortcut.ALT_CTRL), true);
     62    }
     63
     64    Map<Way, List<Relation>> relations = new HashMap<>();
     65    Map<Way, Way> oldWays = new HashMap<>();
     66    Map<Relation, Relation> newRelations = new HashMap<>();
     67    Set<Way> deletes = new HashSet<>();
     68
     69    /**
     70     * The action button has been clicked
     71     *
     72     * @param e
     73     *            Action Event
     74     */
     75    @Override
     76    public void actionPerformed(ActionEvent e) {
     77
     78        // List of selected ways
     79        List<Way> ways = new ArrayList<>();
     80        relations.clear();
     81        newRelations.clear();
     82
     83        // For every selected way
     84        for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) {
     85            if (osm instanceof Way && !osm.isDeleted()) {
     86                Way way = (Way) osm;
     87                ways.add(way);
     88                List<Relation> rels = new ArrayList<>();
     89                for (Relation r : OsmPrimitive.getFilteredList(way.getReferrers(), Relation.class)) {
     90                    rels.add(r);
     91                }
     92                relations.put(way, rels);
     93            }
     94        }
     95
     96        List<Way> sel = new ArrayList<>(ways);
     97        Collection<Command> cmds = new LinkedList<>();
     98
     99        // *****
     100        // split
     101        // *****
     102        for (Way way : ways) {
     103            Set<Node> nodes = new HashSet<>();
     104            for (Way opositWay : ways) {
     105                if (way != opositWay) {
     106                    List<NodePos> nodesPos = new LinkedList<>();
     107
     108                    int pos = 0;
     109                    for (Node node : way.getNodes()) {
     110                        int opositPos = 0;
     111                        for (Node opositNode : opositWay.getNodes()) {
     112                            if (node == opositNode) {
     113                                if (opositWay.isClosed()) {
     114                                    opositPos %= opositWay.getNodesCount() - 1;
     115                                }
     116                                nodesPos.add(new NodePos(node, pos, opositPos));
     117                                break;
     118                            }
     119                            opositPos++;
     120                        }
     121                        pos++;
     122                    }
     123
     124                    NodePos start = null;
     125                    NodePos end = null;
     126                    int increment = 0;
     127
     128                    boolean hasFirst = false;
     129                    for (NodePos node : nodesPos) {
     130                        if (start == null) {
     131                            start = node;
     132                        } else {
     133                            if (end == null) {
     134                                if (follows(way, opositWay, start, node, 1)) {
     135                                    end = node;
     136                                    increment = +1;
     137                                } else if (follows(way, opositWay, start, node, -1)) {
     138                                    end = node;
     139                                    increment = -1;
     140                                } else {
     141                                    start = node;
     142                                    end = null;
     143                                }
     144                            } else {
     145                                if (follows(way, opositWay, end, node, increment)) {
     146                                    end = node;
     147                                } else {
     148                                    hasFirst = addNodes(start, end, way, nodes, hasFirst);
     149                                    start = node;
     150                                    end = null;
     151                                }
     152                            }
     153                        }
     154                    }
     155
     156                    if (start != null && end != null) {
     157                        hasFirst = addNodes(start, end, way, nodes, hasFirst);
     158                        start = null;
     159                        end = null;
     160                    }
     161                }
     162            }
     163            if (!nodes.isEmpty() && !way.isClosed() || nodes.size() >= 2) {
     164                List<List<Node>> wayChunks = SplitWayAction.buildSplitChunks(way, new ArrayList<>(nodes));
     165                SplitWayResult result = splitWay(getEditLayer(), way, wayChunks);
     166
     167                cmds.add(result.getCommand());
     168                sel.remove(way);
     169                sel.add(result.getOriginalWay());
     170                sel.addAll(result.getNewWays());
     171                List<Relation> rels = relations.remove(way);
     172                relations.put(result.getOriginalWay(), rels);
     173                for (Way w : result.getNewWays()) {
     174                    relations.put(w, rels);
     175                }
     176            }
     177        }
     178
     179        // *****
     180        // merge
     181        // *****
     182        ways = new ArrayList<>(sel);
     183        while (!ways.isEmpty()) {
     184            Way way = ways.get(0);
     185            List<Way> combine = new ArrayList<>();
     186            combine.add(way);
     187            for (Way opositWay : ways) {
     188                if (way != opositWay
     189                        && way.getNodesCount() == opositWay.getNodesCount()) {
     190                    boolean equals1 = true;
     191                    for (int i = 0; i < way.getNodesCount(); i++) {
     192                        if (way.getNode(i) != opositWay.getNode(i)) {
     193                            equals1 = false;
     194                            break;
     195                        }
     196                    }
     197                    boolean equals2 = true;
     198                    for (int i = 0; i < way.getNodesCount(); i++) {
     199                        if (way.getNode(i) != opositWay.getNode(way
     200                                .getNodesCount()
     201                                - i - 1)) {
     202                            equals2 = false;
     203                            break;
     204                        }
     205                    }
     206                    if (equals1 || equals2) {
     207                        combine.add(opositWay);
     208                    }
     209                }
     210            }
     211            ways.removeAll(combine);
     212            if (combine.size() > 1) {
     213                sel.removeAll(combine);
     214                // combine
     215                Pair<Way, List<Command>> combineResult;
     216                try {
     217                    combineResult = combineWaysWorker(combine);
     218                } catch (UserCancelException ex) {
     219                    return;
     220                }
     221                sel.add(combineResult.a);
     222                cmds.addAll(combineResult.b);
     223            }
     224        }
     225
     226        for (Relation old : newRelations.keySet()) {
     227            cmds.add(new ChangeCommand(old, newRelations.get(old)));
     228        }
     229
     230        List<Way> del = new LinkedList<>();
     231        for (Way w : deletes) {
     232            if (!w.isDeleted()) {
     233                del.add(w);
     234            }
     235        }
     236        if (!del.isEmpty()) {
     237            cmds.add(new DeleteCommand(del));
     238        }
     239
     240        // Commit
     241        Main.main.undoRedo.add(new SequenceCommand(tr("Merge Overlap (combine)"), cmds));
     242        getCurrentDataSet().setSelected(sel);
     243        Main.map.repaint();
     244
     245        relations.clear();
     246        newRelations.clear();
     247        oldWays.clear();
     248    }
     249
     250    private static class NodePos {
     251        Node node;
     252        int pos;
     253        int opositPos;
     254
     255        NodePos(Node n, int p, int op) {
     256            node = n;
     257            pos = p;
     258            opositPos = op;
     259        }
     260
    74261        @Override
    75         public void actionPerformed(ActionEvent e) {
    76 
    77                 // List of selected ways
    78                 List<Way> ways = new ArrayList<>();
    79                 relations.clear();
    80                 newRelations.clear();
    81 
    82                 // For every selected way
    83                 for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) {
    84                         if (osm instanceof Way && !osm.isDeleted()) {
    85                                 Way way = (Way) osm;
    86                                 ways.add(way);
    87                                 List<Relation> rels = new ArrayList<>();
    88                                 for (Relation r : OsmPrimitive.getFilteredList(way
    89                                                 .getReferrers(), Relation.class)) {
    90                                         rels.add(r);
    91                                 }
    92                                 relations.put(way, rels);
    93                         }
    94                 }
    95 
    96                 List<Way> sel = new ArrayList<>(ways);
    97                 Collection<Command> cmds = new LinkedList<>();
    98 
    99                 // *****
    100                 // split
    101                 // *****
    102                 for (Way way : ways) {
    103                         Set<Node> nodes = new HashSet<>();
    104                         for (Way opositWay : ways) {
    105                                 if (way != opositWay) {
    106                                         List<NodePos> nodesPos = new LinkedList<>();
    107 
    108                                         int pos = 0;
    109                                         for (Node node : way.getNodes()) {
    110                                                 int opositPos = 0;
    111                                                 for (Node opositNode : opositWay.getNodes()) {
    112                                                         if (node == opositNode) {
    113                                                                 if (opositWay.isClosed()) {
    114                                                                         opositPos %= opositWay.getNodesCount() - 1;
    115                                                                 }
    116                                                                 nodesPos.add(new NodePos(node, pos, opositPos));
    117                                                                 break;
    118                                                         }
    119                                                         opositPos++;
    120                                                 }
    121                                                 pos++;
    122                                         }
    123 
    124                                         NodePos start = null;
    125                                         NodePos end = null;
    126                                         int increment = 0;
    127 
    128                                         boolean hasFirst = false;
    129                                         for (NodePos node : nodesPos) {
    130                                                 if (start == null) {
    131                                                         start = node;
    132                                                 } else {
    133                                                         if (end == null) {
    134                                                                 if (follows(way, opositWay, start, node, 1)) {
    135                                                                         end = node;
    136                                                                         increment = +1;
    137                                                                 } else if (follows(way, opositWay, start, node,
    138                                                                                 -1)) {
    139                                                                         end = node;
    140                                                                         increment = -1;
    141                                                                 } else {
    142                                                                         start = node;
    143                                                                         end = null;
    144                                                                 }
    145                                                         } else {
    146                                                                 if (follows(way, opositWay, end, node,
    147                                                                                 increment)) {
    148                                                                         end = node;
    149                                                                 } else {
    150                                                                         hasFirst = addNodes(start, end, way, nodes,
    151                                                                                         hasFirst);
    152                                                                         start = node;
    153                                                                         end = null;
    154                                                                 }
    155                                                         }
    156                                                 }
    157                                         }
    158 
    159                                         if (start != null && end != null) {
    160                                                 hasFirst = addNodes(start, end, way, nodes, hasFirst);
    161                                                 start = null;
    162                                                 end = null;
    163                                         }
    164                                 }
    165                         }
    166                         if (!nodes.isEmpty() && !way.isClosed() || nodes.size() >= 2) {
    167                                 List<List<Node>> wayChunks = SplitWayAction.buildSplitChunks(
    168                                                 way, new ArrayList<>(nodes));
    169                                 SplitWayResult result = splitWay(getEditLayer(), way, wayChunks);
    170 
    171                                 cmds.add(result.getCommand());
    172                                 sel.remove(way);
    173                                 sel.add(result.getOriginalWay());
    174                                 sel.addAll(result.getNewWays());
    175                                 List<Relation> rels = relations.remove(way);
    176                                 relations.put(result.getOriginalWay(), rels);
    177                                 for (Way w : result.getNewWays()) {
    178                                         relations.put(w, rels);
    179                                 }
    180                         }
    181                 }
    182 
    183                 // *****
    184                 // merge
    185                 // *****
    186                 ways = new ArrayList<>(sel);
    187                 while (!ways.isEmpty()) {
    188                         Way way = ways.get(0);
    189                         List<Way> combine = new ArrayList<>();
    190                         combine.add(way);
    191                         for (Way opositWay : ways) {
    192                                 if (way != opositWay
    193                                                 && way.getNodesCount() == opositWay.getNodesCount()) {
    194                                         boolean equals1 = true;
    195                                         for (int i = 0; i < way.getNodesCount(); i++) {
    196                                                 if (way.getNode(i) != opositWay.getNode(i)) {
    197                                                         equals1 = false;
    198                                                         break;
    199                                                 }
    200                                         }
    201                                         boolean equals2 = true;
    202                                         for (int i = 0; i < way.getNodesCount(); i++) {
    203                                                 if (way.getNode(i) != opositWay.getNode(way
    204                                                                 .getNodesCount()
    205                                                                 - i - 1)) {
    206                                                         equals2 = false;
    207                                                         break;
    208                                                 }
    209                                         }
    210                                         if (equals1 || equals2) {
    211                                                 combine.add(opositWay);
    212                                         }
    213                                 }
    214                         }
    215                         ways.removeAll(combine);
    216                         if (combine.size() > 1) {
    217                                 sel.removeAll(combine);
    218                                 // combine
    219                                 Pair<Way, List<Command>> combineResult;
    220                                 try {
    221                                         combineResult = combineWaysWorker(combine);
    222                                 } catch (UserCancelException e1) {
    223                                         return;
    224                                 }
    225                                 sel.add(combineResult.a);
    226                                 cmds.addAll(combineResult.b);
    227                         }
    228                 }
    229 
    230                 for (Relation old : newRelations.keySet()) {
    231                         cmds.add(new ChangeCommand(old, newRelations.get(old)));
    232                 }
    233 
    234                 List<Way> del = new LinkedList<>();
    235                 for (Way w : deletes) {
    236                         if (!w.isDeleted()) {
    237                                 del.add(w);
    238                         }
    239                 }
    240                 if (!del.isEmpty()) {
    241                         cmds.add(new DeleteCommand(del));
    242                 }
    243 
    244                 // Commit
    245                 Main.main.undoRedo.add(new SequenceCommand(
    246                                 tr("Merge Overlap (combine)"), cmds));
    247                 getCurrentDataSet().setSelected(sel);
    248                 Main.map.repaint();
    249 
    250                 relations.clear();
    251                 newRelations.clear();
    252                 oldWays.clear();
    253         }
    254 
    255         private class NodePos {
    256                 Node node;
    257                 int pos;
    258                 int opositPos;
    259 
    260                 NodePos(Node n, int p, int op) {
    261                         node = n;
    262                         pos = p;
    263                         opositPos = op;
    264                 }
    265 
    266                 @Override
    267                 public String toString() {
    268                         return "NodePos: " + pos + ", " + opositPos + ", " + node;
    269                 }
    270         }
    271 
    272         private boolean addNodes(NodePos start, NodePos end, Way way,
    273                         Set<Node> nodes, boolean hasFirst) {
    274                 if (way.isClosed()
    275                                 || (start.node != way.getNode(0) && start.node != way
    276                                                 .getNode(way.getNodesCount() - 1))) {
    277                         hasFirst = hasFirst || start.node == way.getNode(0);
    278                         nodes.add(start.node);
    279                 }
    280                 if (way.isClosed()
    281                                 || (end.node != way.getNode(0) && end.node != way.getNode(way
    282                                                 .getNodesCount() - 1))) {
    283                         if (hasFirst && (end.node == way.getNode(way.getNodesCount() - 1))) {
    284                                 nodes.remove(way.getNode(0));
    285                         } else {
    286                                 nodes.add(end.node);
    287                         }
    288                 }
    289                 return hasFirst;
    290         }
    291 
    292         private boolean follows(Way way1, Way way2, NodePos np1, NodePos np2,
    293                         int incr) {
    294                 if (way2.isClosed() && incr == 1
    295                                 && np1.opositPos == way2.getNodesCount() - 2) {
    296                         return np2.pos == np1.pos + 1 && np2.opositPos == 0;
    297                 } else if (way2.isClosed() && incr == 1 && np1.opositPos == 0) {
    298                         return np2.pos == np1.pos && np2.opositPos == 0
    299                                         || np2.pos == np1.pos + 1 && np2.opositPos == 1;
    300                 } else if (way2.isClosed() && incr == -1 && np1.opositPos == 0) {
    301                         return np2.pos == np1.pos && np2.opositPos == 0
    302                                         || np2.pos == np1.pos + 1
    303                                         && np2.opositPos == way2.getNodesCount() - 2;
    304                 } else {
    305                         return np2.pos == np1.pos + 1
    306                                         && np2.opositPos == np1.opositPos + incr;
    307                 }
    308         }
    309 
    310         /**
    311          * Splits a way
    312          *
    313          * @param layer
    314          * @param way
    315          * @param wayChunks
    316          * @return
    317          */
    318         private SplitWayResult splitWay(OsmDataLayer layer, Way way,
    319                         List<List<Node>> wayChunks) {
    320                 // build a list of commands, and also a new selection list
    321                 Collection<Command> commandList = new ArrayList<>(wayChunks
    322                                 .size());
    323 
    324                 Iterator<List<Node>> chunkIt = wayChunks.iterator();
    325                 Collection<String> nowarnroles = Main.pref.getCollection(
    326                                 "way.split.roles.nowarn", Arrays.asList(new String[] { "outer",
    327                                                 "inner", "forward", "backward" }));
    328 
    329                 // First, change the original way
    330                 Way changedWay = new Way(way);
    331                 oldWays.put(changedWay, way);
    332                 changedWay.setNodes(chunkIt.next());
    333                 commandList.add(new ChangeCommand(way, changedWay));
    334 
    335                 List<Way> newWays = new ArrayList<>();
    336                 // Second, create new ways
    337                 while (chunkIt.hasNext()) {
    338                         Way wayToAdd = new Way();
    339                         wayToAdd.setKeys(way.getKeys());
    340                         newWays.add(wayToAdd);
    341                         wayToAdd.setNodes(chunkIt.next());
    342                         commandList.add(new AddCommand(layer, wayToAdd));
    343                 }
    344                 boolean warnmerole = false;
    345                 boolean warnme = false;
    346                 // now copy all relations to new way also
    347 
    348                 for (Relation r : getParentRelations(way)) {
    349                         if (!r.isUsable()) {
    350                                 continue;
    351                         }
    352                         Relation c = null;
    353                         String type = r.get("type");
    354                         if (type == null) {
    355                                 type = "";
    356                         }
    357 
    358                         int i_c = 0, i_r = 0;
    359                         List<RelationMember> relationMembers = r.getMembers();
    360                         for (RelationMember rm : relationMembers) {
    361                                 if (rm.isWay() && rm.getMember() == way) {
    362                                         boolean insert = true;
    363                                         if ("restriction".equals(type)) {
    364                                                 /*
    365                                                  * this code assumes the restriction is correct. No real
    366                                                  * error checking done
    367                                                  */
    368                                                 String role = rm.getRole();
    369                                                 if ("from".equals(role) || "to".equals(role)) {
    370                                                         OsmPrimitive via = null;
    371                                                         for (RelationMember rmv : r.getMembers()) {
    372                                                                 if ("via".equals(rmv.getRole())) {
    373                                                                         via = rmv.getMember();
    374                                                                 }
    375                                                         }
    376                                                         List<Node> nodes = new ArrayList<>();
    377                                                         if (via != null) {
    378                                                                 if (via instanceof Node) {
    379                                                                         nodes.add((Node) via);
    380                                                                 } else if (via instanceof Way) {
    381                                                                         nodes.add(((Way) via).lastNode());
    382                                                                         nodes.add(((Way) via).firstNode());
    383                                                                 }
    384                                                         }
    385                                                         Way res = null;
    386                                                         for (Node n : nodes) {
    387                                                                 if (changedWay.isFirstLastNode(n)) {
    388                                                                         res = way;
    389                                                                 }
    390                                                         }
    391                                                         if (res == null) {
    392                                                                 for (Way wayToAdd : newWays) {
    393                                                                         for (Node n : nodes) {
    394                                                                                 if (wayToAdd.isFirstLastNode(n)) {
    395                                                                                         res = wayToAdd;
    396                                                                                 }
    397                                                                         }
    398                                                                 }
    399                                                                 if (res != null) {
    400                                                                         if (c == null) {
    401                                                                                 c = getNew(r);
    402                                                                         }
    403                                                                         c.addMember(new RelationMember(role, res));
    404                                                                         c.removeMembersFor(way);
    405                                                                         insert = false;
    406                                                                 }
    407                                                         } else {
    408                                                                 insert = false;
    409                                                         }
    410                                                 } else if (!"via".equals(role)) {
    411                                                         warnme = true;
    412                                                 }
    413                                         } else if (!("route".equals(type))
    414                                                         && !("multipolygon".equals(type))) {
    415                                                 warnme = true;
    416                                         }
    417                                         if (c == null) {
    418                                                 c = getNew(r);
    419                                         }
    420 
    421                                         if (insert) {
    422                                                 if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) {
    423                                                         warnmerole = true;
    424                                                 }
    425 
    426                                                 Boolean backwards = null;
    427                                                 int k = 1;
    428                                                 while (i_r - k >= 0 || i_r + k < relationMembers.size()) {
    429                                                         if ((i_r - k >= 0)
    430                                                                         && relationMembers.get(i_r - k).isWay()) {
    431                                                                 Way w = relationMembers.get(i_r - k).getWay();
    432                                                                 if ((w.lastNode() == way.firstNode())
    433                                                                                 || w.firstNode() == way.firstNode()) {
    434                                                                         backwards = false;
    435                                                                 } else if ((w.firstNode() == way.lastNode())
    436                                                                                 || w.lastNode() == way.lastNode()) {
    437                                                                         backwards = true;
    438                                                                 }
    439                                                                 break;
    440                                                         }
    441                                                         if ((i_r + k < relationMembers.size())
    442                                                                         && relationMembers.get(i_r + k).isWay()) {
    443                                                                 Way w = relationMembers.get(i_r + k).getWay();
    444                                                                 if ((w.lastNode() == way.firstNode())
    445                                                                                 || w.firstNode() == way.firstNode()) {
    446                                                                         backwards = true;
    447                                                                 } else if ((w.firstNode() == way.lastNode())
    448                                                                                 || w.lastNode() == way.lastNode()) {
    449                                                                         backwards = false;
    450                                                                 }
    451                                                                 break;
    452                                                         }
    453                                                         k++;
    454                                                 }
    455 
    456                                                 int j = i_c;
    457                                                 for (Way wayToAdd : newWays) {
    458                                                         RelationMember em = new RelationMember(
    459                                                                         rm.getRole(), wayToAdd);
    460                                                         j++;
    461                                                         if ((backwards != null) && backwards) {
    462                                                                 c.addMember(i_c, em);
    463                                                         } else {
    464                                                                 c.addMember(j, em);
    465                                                         }
    466                                                 }
    467                                                 i_c = j;
    468                                         }
    469                                 }
    470                                 i_c++;
    471                                 i_r++;
    472                         }
    473 
    474                         if (c != null) {
    475                                 // commandList.add(new ChangeCommand(layer, r, c));
    476                                 newRelations.put(r, c);
    477                         }
    478                 }
    479                 if (warnmerole) {
    480                         JOptionPane
    481                                         .showMessageDialog(
    482                                                         Main.parent,
    483                                                         tr("<html>A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"),
    484                                                         tr("Warning"), JOptionPane.WARNING_MESSAGE);
    485                 } else if (warnme) {
    486                         JOptionPane
    487                                         .showMessageDialog(
    488                                                         Main.parent,
    489                                                         tr("<html>A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"),
    490                                                         tr("Warning"), JOptionPane.WARNING_MESSAGE);
    491                 }
    492 
    493                 return new SplitWayResult(
    494                                 new SequenceCommand(tr("Split way"), commandList), null,
    495                                 changedWay, newWays);
    496         }
    497 
    498         /**
    499          * @param ways
    500          * @return null if ways cannot be combined. Otherwise returns the combined
    501          *         ways and the commands to combine
    502          * @throws UserCancelException
    503          */
    504         private Pair<Way, List<Command>> combineWaysWorker(Collection<Way> ways)
    505                         throws UserCancelException {
    506 
    507                 // prepare and clean the list of ways to combine
    508                 if (ways == null || ways.isEmpty())
    509                         return null;
    510                 ways.remove(null); // just in case - remove all null ways from the
    511                                                         // collection
    512 
    513                 // remove duplicates, preserving order
    514                 ways = new LinkedHashSet<>(ways);
    515 
    516                 // try to build a new way which includes all the combined ways
    517                 NodeGraph graph = NodeGraph.createUndirectedGraphFromNodeWays(ways);
    518                 List<Node> path = graph.buildSpanningPath();
    519 
    520                 // check whether any ways have been reversed in the process
    521                 // and build the collection of tags used by the ways to combine
    522                 TagCollection wayTags = TagCollection.unionOfAllPrimitives(ways);
    523 
    524                 List<Way> reversedWays = new LinkedList<>();
    525                 List<Way> unreversedWays = new LinkedList<>();
    526                 for (Way w : ways) {
    527                         if ((path.indexOf(w.getNode(0)) + 1) == path.lastIndexOf(w
    528                                         .getNode(1))) {
    529                                 unreversedWays.add(w);
    530                         } else {
    531                                 reversedWays.add(w);
    532                         }
    533                 }
    534                 // reverse path if all ways have been reversed
    535                 if (unreversedWays.isEmpty()) {
    536                         Collections.reverse(path);
    537                         unreversedWays = reversedWays;
    538                         reversedWays = null;
    539                 }
    540                 if ((reversedWays != null) && !reversedWays.isEmpty()) {
    541                         // filter out ways that have no direction-dependent tags
    542                         unreversedWays = ReverseWayTagCorrector
    543                                         .irreversibleWays(unreversedWays);
    544                         reversedWays = ReverseWayTagCorrector
    545                                         .irreversibleWays(reversedWays);
    546                         // reverse path if there are more reversed than unreversed ways with
    547                         // direction-dependent tags
    548                         if (reversedWays.size() > unreversedWays.size()) {
    549                                 Collections.reverse(path);
    550                                 List<Way> tempWays = unreversedWays;
    551                                 unreversedWays = reversedWays;
    552                                 reversedWays = tempWays;
    553                         }
    554                         // if there are still reversed ways with direction-dependent tags,
    555                         // reverse their tags
    556                         if (!reversedWays.isEmpty()) {
    557                                 List<Way> unreversedTagWays = new ArrayList<>(ways);
    558                                 unreversedTagWays.removeAll(reversedWays);
    559                                 ReverseWayTagCorrector reverseWayTagCorrector = new ReverseWayTagCorrector();
    560                                 List<Way> reversedTagWays = new ArrayList<>();
    561                                 Collection<Command> changePropertyCommands = null;
    562                                 for (Way w : reversedWays) {
    563                                         Way wnew = new Way(w);
    564                                         reversedTagWays.add(wnew);
    565                                         changePropertyCommands = reverseWayTagCorrector.execute(w,
    566                                                         wnew);
    567                                 }
    568                                 if ((changePropertyCommands != null)
    569                                                 && !changePropertyCommands.isEmpty()) {
    570                                         for (Command c : changePropertyCommands) {
    571                                                 c.executeCommand();
    572                                         }
    573                                 }
    574                                 wayTags = TagCollection.unionOfAllPrimitives(reversedTagWays);
    575                                 wayTags.add(TagCollection
    576                                                 .unionOfAllPrimitives(unreversedTagWays));
    577                         }
    578                 }
    579 
    580                 // create the new way and apply the new node list
    581                 Way targetWay = getTargetWay(ways);
    582                 Way modifiedTargetWay = new Way(targetWay);
    583                 modifiedTargetWay.setNodes(path);
    584 
    585                 TagCollection completeWayTags = new TagCollection(wayTags);
    586                 combineTigerTags(completeWayTags);
    587                 normalizeTagCollectionBeforeEditing(completeWayTags, ways);
    588                 TagCollection tagsToEdit = new TagCollection(completeWayTags);
    589                 completeTagCollectionForEditing(tagsToEdit);
    590 
    591                 MyCombinePrimitiveResolverDialog dialog = MyCombinePrimitiveResolverDialog
    592                                 .getInstance();
    593                 dialog.getTagConflictResolverModel().populate(tagsToEdit,
    594                                 completeWayTags.getKeysWithMultipleValues());
    595                 dialog.setTargetPrimitive(targetWay);
    596                 Set<Relation> parentRelations = getParentRelations(ways);
    597                 dialog.getRelationMemberConflictResolverModel().populate(
    598                                 parentRelations, ways, oldWays);
    599                 dialog.prepareDefaultDecisions();
    600 
    601                 // resolve tag conflicts if necessary
    602                 if (askForMergeTag(ways) || duplicateParentRelations(ways)) {
    603                         dialog.setVisible(true);
    604                         if (dialog.isCanceled())
    605                                 throw new UserCancelException();
    606                 }
    607 
    608                 LinkedList<Command> cmds = new LinkedList<>();
    609                 deletes.addAll(ways);
    610                 deletes.remove(targetWay);
    611 
    612                 cmds.add(new ChangeCommand(targetWay, modifiedTargetWay));
    613                 cmds.addAll(dialog.buildWayResolutionCommands());
    614                 dialog.buildRelationCorrespondance(newRelations, oldWays);
    615 
    616                 return new Pair<Way, List<Command>>(targetWay, cmds);
    617         }
    618 
    619         private static Way getTargetWay(Collection<Way> combinedWays) {
    620                 // init with an arbitrary way
    621                 Way targetWay = combinedWays.iterator().next();
    622 
    623                 // look for the first way already existing on
    624                 // the server
    625                 for (Way w : combinedWays) {
    626                         targetWay = w;
    627                         if (!w.isNew()) {
    628                                 break;
    629                         }
    630                 }
    631                 return targetWay;
    632         }
    633 
    634         /**
    635          * @return has tag to be merged (=> ask)
    636          */
    637         private static boolean askForMergeTag(Collection<Way> ways) {
    638                 for (Way way : ways) {
    639                         for (Way oposite : ways) {
    640                                 for (String key : way.getKeys().keySet()) {
    641                                         if (!"source".equals(key) && oposite.hasKey(key)
    642                                                         && !way.get(key).equals(oposite.get(key))) {
    643                                                 return true;
    644                                         }
    645                                 }
    646                         }
    647                 }
    648                 return false;
    649         }
    650 
    651         /**
    652          * @return has duplicate parent relation
    653          */
    654         private boolean duplicateParentRelations(Collection<Way> ways) {
    655                 Set<Relation> relations = new HashSet<>();
    656                 for (Way w : ways) {
    657                         List<Relation> rs = getParentRelations(w);
    658                         for (Relation r : rs) {
    659                                 if (relations.contains(r)) {
    660                                         return true;
    661                                 }
    662                         }
    663                         relations.addAll(rs);
    664                 }
    665                 return false;
    666         }
    667 
    668         /**
    669          * Replies the set of referring relations
    670          *
    671          * @return the set of referring relations
    672          */
    673         private List<Relation> getParentRelations(Way way) {
    674                 List<Relation> rels = new ArrayList<>();
    675                 for (Relation r : relations.get(way)) {
    676                         if (newRelations.containsKey(r)) {
    677                                 rels.add(newRelations.get(r));
    678                         } else {
    679                                 rels.add(r);
    680                         }
    681                 }
    682                 return rels;
    683         }
    684 
    685         private Relation getNew(Relation r) {
    686                 return getNew(r, newRelations);
    687         }
    688 
    689         public static Relation getNew(Relation r,
    690                         Map<Relation, Relation> newRelations) {
    691                 if (newRelations.containsValue(r)) {
    692                         return r;
    693                 } else {
    694                         Relation c = new Relation(r);
    695                         newRelations.put(r, c);
    696                         return c;
    697                 }
    698         }
     262        public String toString() {
     263            return "NodePos: " + pos + ", " + opositPos + ", " + node;
     264        }
     265    }
     266
     267    private boolean addNodes(NodePos start, NodePos end, Way way,
     268            Set<Node> nodes, boolean hasFirst) {
     269        if (way.isClosed() || (start.node != way.getNode(0) && start.node != way.getNode(way.getNodesCount() - 1))) {
     270            hasFirst = hasFirst || start.node == way.getNode(0);
     271            nodes.add(start.node);
     272        }
     273        if (way.isClosed() || (end.node != way.getNode(0) && end.node != way.getNode(way.getNodesCount() - 1))) {
     274            if (hasFirst && (end.node == way.getNode(way.getNodesCount() - 1))) {
     275                nodes.remove(way.getNode(0));
     276            } else {
     277                nodes.add(end.node);
     278            }
     279        }
     280        return hasFirst;
     281    }
     282
     283    private boolean follows(Way way1, Way way2, NodePos np1, NodePos np2,
     284            int incr) {
     285        if (way2.isClosed() && incr == 1
     286                && np1.opositPos == way2.getNodesCount() - 2) {
     287            return np2.pos == np1.pos + 1 && np2.opositPos == 0;
     288        } else if (way2.isClosed() && incr == 1 && np1.opositPos == 0) {
     289            return np2.pos == np1.pos && np2.opositPos == 0
     290                    || np2.pos == np1.pos + 1 && np2.opositPos == 1;
     291        } else if (way2.isClosed() && incr == -1 && np1.opositPos == 0) {
     292            return np2.pos == np1.pos && np2.opositPos == 0
     293                    || np2.pos == np1.pos + 1
     294                    && np2.opositPos == way2.getNodesCount() - 2;
     295        } else {
     296            return np2.pos == np1.pos + 1
     297                    && np2.opositPos == np1.opositPos + incr;
     298        }
     299    }
     300
     301    /**
     302     * Splits a way
     303     *
     304     * @param layer
     305     * @param way
     306     * @param wayChunks
     307     * @return
     308     */
     309    private SplitWayResult splitWay(OsmDataLayer layer, Way way,
     310            List<List<Node>> wayChunks) {
     311        // build a list of commands, and also a new selection list
     312        Collection<Command> commandList = new ArrayList<>(wayChunks
     313                .size());
     314
     315        Iterator<List<Node>> chunkIt = wayChunks.iterator();
     316        Collection<String> nowarnroles = Main.pref.getCollection(
     317                "way.split.roles.nowarn", Arrays.asList(new String[] { "outer",
     318                        "inner", "forward", "backward" }));
     319
     320        // First, change the original way
     321        Way changedWay = new Way(way);
     322        oldWays.put(changedWay, way);
     323        changedWay.setNodes(chunkIt.next());
     324        commandList.add(new ChangeCommand(way, changedWay));
     325
     326        List<Way> newWays = new ArrayList<>();
     327        // Second, create new ways
     328        while (chunkIt.hasNext()) {
     329            Way wayToAdd = new Way();
     330            wayToAdd.setKeys(way.getKeys());
     331            newWays.add(wayToAdd);
     332            wayToAdd.setNodes(chunkIt.next());
     333            commandList.add(new AddCommand(layer, wayToAdd));
     334        }
     335        boolean warnmerole = false;
     336        boolean warnme = false;
     337        // now copy all relations to new way also
     338
     339        for (Relation r : getParentRelations(way)) {
     340            if (!r.isUsable()) {
     341                continue;
     342            }
     343            Relation c = null;
     344            String type = r.get("type");
     345            if (type == null) {
     346                type = "";
     347            }
     348
     349            int ic = 0, ir = 0;
     350            List<RelationMember> relationMembers = r.getMembers();
     351            for (RelationMember rm : relationMembers) {
     352                if (rm.isWay() && rm.getMember() == way) {
     353                    boolean insert = true;
     354                    if ("restriction".equals(type)) {
     355                        /*
     356                         * this code assumes the restriction is correct. No real
     357                         * error checking done
     358                         */
     359                        String role = rm.getRole();
     360                        if ("from".equals(role) || "to".equals(role)) {
     361                            OsmPrimitive via = null;
     362                            for (RelationMember rmv : r.getMembers()) {
     363                                if ("via".equals(rmv.getRole())) {
     364                                    via = rmv.getMember();
     365                                }
     366                            }
     367                            List<Node> nodes = new ArrayList<>();
     368                            if (via != null) {
     369                                if (via instanceof Node) {
     370                                    nodes.add((Node) via);
     371                                } else if (via instanceof Way) {
     372                                    nodes.add(((Way) via).lastNode());
     373                                    nodes.add(((Way) via).firstNode());
     374                                }
     375                            }
     376                            Way res = null;
     377                            for (Node n : nodes) {
     378                                if (changedWay.isFirstLastNode(n)) {
     379                                    res = way;
     380                                }
     381                            }
     382                            if (res == null) {
     383                                for (Way wayToAdd : newWays) {
     384                                    for (Node n : nodes) {
     385                                        if (wayToAdd.isFirstLastNode(n)) {
     386                                            res = wayToAdd;
     387                                        }
     388                                    }
     389                                }
     390                                if (res != null) {
     391                                    if (c == null) {
     392                                        c = getNew(r);
     393                                    }
     394                                    c.addMember(new RelationMember(role, res));
     395                                    c.removeMembersFor(way);
     396                                    insert = false;
     397                                }
     398                            } else {
     399                                insert = false;
     400                            }
     401                        } else if (!"via".equals(role)) {
     402                            warnme = true;
     403                        }
     404                    } else if (!("route".equals(type))
     405                            && !("multipolygon".equals(type))) {
     406                        warnme = true;
     407                    }
     408                    if (c == null) {
     409                        c = getNew(r);
     410                    }
     411
     412                    if (insert) {
     413                        if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) {
     414                            warnmerole = true;
     415                        }
     416
     417                        Boolean backwards = null;
     418                        int k = 1;
     419                        while (ir - k >= 0 || ir + k < relationMembers.size()) {
     420                            if ((ir - k >= 0)
     421                                    && relationMembers.get(ir - k).isWay()) {
     422                                Way w = relationMembers.get(ir - k).getWay();
     423                                if ((w.lastNode() == way.firstNode())
     424                                        || w.firstNode() == way.firstNode()) {
     425                                    backwards = false;
     426                                } else if ((w.firstNode() == way.lastNode())
     427                                        || w.lastNode() == way.lastNode()) {
     428                                    backwards = true;
     429                                }
     430                                break;
     431                            }
     432                            if ((ir + k < relationMembers.size())
     433                                    && relationMembers.get(ir + k).isWay()) {
     434                                Way w = relationMembers.get(ir + k).getWay();
     435                                if ((w.lastNode() == way.firstNode())
     436                                        || w.firstNode() == way.firstNode()) {
     437                                    backwards = true;
     438                                } else if ((w.firstNode() == way.lastNode())
     439                                        || w.lastNode() == way.lastNode()) {
     440                                    backwards = false;
     441                                }
     442                                break;
     443                            }
     444                            k++;
     445                        }
     446
     447                        int j = ic;
     448                        for (Way wayToAdd : newWays) {
     449                            RelationMember em = new RelationMember(
     450                                    rm.getRole(), wayToAdd);
     451                            j++;
     452                            if ((backwards != null) && backwards) {
     453                                c.addMember(ic, em);
     454                            } else {
     455                                c.addMember(j, em);
     456                            }
     457                        }
     458                        ic = j;
     459                    }
     460                }
     461                ic++;
     462                ir++;
     463            }
     464
     465            if (c != null) {
     466                // commandList.add(new ChangeCommand(layer, r, c));
     467                newRelations.put(r, c);
     468            }
     469        }
     470        if (warnmerole) {
     471            JOptionPane.showMessageDialog(
     472                Main.parent,
     473                tr("<html>A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"),
     474                tr("Warning"), JOptionPane.WARNING_MESSAGE);
     475        } else if (warnme) {
     476            JOptionPane.showMessageDialog(
     477                Main.parent,
     478                tr("<html>A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"),
     479                tr("Warning"), JOptionPane.WARNING_MESSAGE);
     480        }
     481
     482        return new SplitWayResult(
     483                new SequenceCommand(tr("Split way"), commandList), null,
     484                changedWay, newWays);
     485    }
     486
     487    /**
     488     * @param ways
     489     * @return null if ways cannot be combined. Otherwise returns the combined
     490     *         ways and the commands to combine
     491     * @throws UserCancelException
     492     */
     493    private Pair<Way, List<Command>> combineWaysWorker(Collection<Way> ways)
     494            throws UserCancelException {
     495
     496        // prepare and clean the list of ways to combine
     497        if (ways == null || ways.isEmpty())
     498            return null;
     499        ways.remove(null); // just in case - remove all null ways from the
     500                            // collection
     501
     502        // remove duplicates, preserving order
     503        ways = new LinkedHashSet<>(ways);
     504
     505        // try to build a new way which includes all the combined ways
     506        NodeGraph graph = NodeGraph.createUndirectedGraphFromNodeWays(ways);
     507        List<Node> path = graph.buildSpanningPath();
     508
     509        // check whether any ways have been reversed in the process
     510        // and build the collection of tags used by the ways to combine
     511        TagCollection wayTags = TagCollection.unionOfAllPrimitives(ways);
     512
     513        List<Way> reversedWays = new LinkedList<>();
     514        List<Way> unreversedWays = new LinkedList<>();
     515        for (Way w : ways) {
     516            if ((path.indexOf(w.getNode(0)) + 1) == path.lastIndexOf(w
     517                    .getNode(1))) {
     518                unreversedWays.add(w);
     519            } else {
     520                reversedWays.add(w);
     521            }
     522        }
     523        // reverse path if all ways have been reversed
     524        if (unreversedWays.isEmpty()) {
     525            Collections.reverse(path);
     526            unreversedWays = reversedWays;
     527            reversedWays = null;
     528        }
     529        if ((reversedWays != null) && !reversedWays.isEmpty()) {
     530            // filter out ways that have no direction-dependent tags
     531            unreversedWays = ReverseWayTagCorrector
     532                    .irreversibleWays(unreversedWays);
     533            reversedWays = ReverseWayTagCorrector
     534                    .irreversibleWays(reversedWays);
     535            // reverse path if there are more reversed than unreversed ways with
     536            // direction-dependent tags
     537            if (reversedWays.size() > unreversedWays.size()) {
     538                Collections.reverse(path);
     539                List<Way> tempWays = unreversedWays;
     540                unreversedWays = reversedWays;
     541                reversedWays = tempWays;
     542            }
     543            // if there are still reversed ways with direction-dependent tags,
     544            // reverse their tags
     545            if (!reversedWays.isEmpty()) {
     546                List<Way> unreversedTagWays = new ArrayList<>(ways);
     547                unreversedTagWays.removeAll(reversedWays);
     548                ReverseWayTagCorrector reverseWayTagCorrector = new ReverseWayTagCorrector();
     549                List<Way> reversedTagWays = new ArrayList<>();
     550                Collection<Command> changePropertyCommands = null;
     551                for (Way w : reversedWays) {
     552                    Way wnew = new Way(w);
     553                    reversedTagWays.add(wnew);
     554                    changePropertyCommands = reverseWayTagCorrector.execute(w,
     555                            wnew);
     556                }
     557                if ((changePropertyCommands != null)
     558                        && !changePropertyCommands.isEmpty()) {
     559                    for (Command c : changePropertyCommands) {
     560                        c.executeCommand();
     561                    }
     562                }
     563                wayTags = TagCollection.unionOfAllPrimitives(reversedTagWays);
     564                wayTags.add(TagCollection.unionOfAllPrimitives(unreversedTagWays));
     565            }
     566        }
     567
     568        // create the new way and apply the new node list
     569        Way targetWay = getTargetWay(ways);
     570        Way modifiedTargetWay = new Way(targetWay);
     571        modifiedTargetWay.setNodes(path);
     572
     573        TagCollection completeWayTags = new TagCollection(wayTags);
     574        combineTigerTags(completeWayTags);
     575        normalizeTagCollectionBeforeEditing(completeWayTags, ways);
     576        TagCollection tagsToEdit = new TagCollection(completeWayTags);
     577        completeTagCollectionForEditing(tagsToEdit);
     578
     579        MyCombinePrimitiveResolverDialog dialog = MyCombinePrimitiveResolverDialog.getInstance();
     580        dialog.getTagConflictResolverModel().populate(tagsToEdit, completeWayTags.getKeysWithMultipleValues());
     581        dialog.setTargetPrimitive(targetWay);
     582        Set<Relation> parentRelations = getParentRelations(ways);
     583        dialog.getRelationMemberConflictResolverModel().populate(parentRelations, ways, oldWays);
     584        dialog.prepareDefaultDecisions();
     585
     586        // resolve tag conflicts if necessary
     587        if (askForMergeTag(ways) || duplicateParentRelations(ways)) {
     588            dialog.setVisible(true);
     589            if (dialog.isCanceled())
     590                throw new UserCancelException();
     591        }
     592
     593        List<Command> cmds = new LinkedList<>();
     594        deletes.addAll(ways);
     595        deletes.remove(targetWay);
     596
     597        cmds.add(new ChangeCommand(targetWay, modifiedTargetWay));
     598        cmds.addAll(dialog.buildWayResolutionCommands());
     599        dialog.buildRelationCorrespondance(newRelations, oldWays);
     600
     601        return new Pair<>(targetWay, cmds);
     602    }
     603
     604    private static Way getTargetWay(Collection<Way> combinedWays) {
     605        // init with an arbitrary way
     606        Way targetWay = combinedWays.iterator().next();
     607
     608        // look for the first way already existing on the server
     609        for (Way w : combinedWays) {
     610            targetWay = w;
     611            if (!w.isNew()) {
     612                break;
     613            }
     614        }
     615        return targetWay;
     616    }
     617
     618    /**
     619     * @return has tag to be merged (=> ask)
     620     */
     621    private static boolean askForMergeTag(Collection<Way> ways) {
     622        for (Way way : ways) {
     623            for (Way oposite : ways) {
     624                for (String key : way.getKeys().keySet()) {
     625                    if (!"source".equals(key) && oposite.hasKey(key)
     626                            && !way.get(key).equals(oposite.get(key))) {
     627                        return true;
     628                    }
     629                }
     630            }
     631        }
     632        return false;
     633    }
     634
     635    /**
     636     * @return has duplicate parent relation
     637     */
     638    private boolean duplicateParentRelations(Collection<Way> ways) {
     639        Set<Relation> relations = new HashSet<>();
     640        for (Way w : ways) {
     641            List<Relation> rs = getParentRelations(w);
     642            for (Relation r : rs) {
     643                if (relations.contains(r)) {
     644                    return true;
     645                }
     646            }
     647            relations.addAll(rs);
     648        }
     649        return false;
     650    }
     651
     652    /**
     653     * Replies the set of referring relations
     654     *
     655     * @return the set of referring relations
     656     */
     657    private List<Relation> getParentRelations(Way way) {
     658        List<Relation> rels = new ArrayList<>();
     659        for (Relation r : relations.get(way)) {
     660            if (newRelations.containsKey(r)) {
     661                rels.add(newRelations.get(r));
     662            } else {
     663                rels.add(r);
     664            }
     665        }
     666        return rels;
     667    }
     668
     669    private Relation getNew(Relation r) {
     670        return getNew(r, newRelations);
     671    }
     672
     673    public static Relation getNew(Relation r, Map<Relation, Relation> newRelations) {
     674        if (newRelations.containsValue(r)) {
     675            return r;
     676        } else {
     677            Relation c = new Relation(r);
     678            newRelations.put(r, c);
     679            return c;
     680        }
     681    }
    699682/*
    700         private Way getOld(Way r) {
    701                 return getOld(r, oldWays);
    702         }*/
    703 
    704         public static Way getOld(Way w, Map<Way, Way> oldWays) {
    705                 if (oldWays.containsKey(w)) {
    706                         return oldWays.get(w);
    707                 } else {
    708                         return w;
    709                 }
    710         }
    711 
    712         /**
    713         * Replies the set of referring relations
    714         *
    715         * @return the set of referring relations
    716         */
    717         private Set<Relation> getParentRelations(Collection<Way> ways) {
    718                 HashSet<Relation> ret = new HashSet<>();
    719                 for (Way w : ways) {
    720                         ret.addAll(getParentRelations(w));
    721                 }
    722                 return ret;
    723         }
    724 
    725         /** Enable this action only if something is selected */
    726         @Override
    727         protected void updateEnabledState() {
    728                 if (getCurrentDataSet() == null) {
    729                         setEnabled(false);
    730                 } else {
    731                         updateEnabledState(getCurrentDataSet().getSelected());
    732                 }
    733         }
    734 
    735         /** Enable this action only if something is selected */
    736         @Override
    737         protected void updateEnabledState(
    738                         Collection<? extends OsmPrimitive> selection) {
    739                 if (selection == null) {
    740                         setEnabled(false);
    741                         return;
    742                 }
    743                 for (OsmPrimitive primitive : selection) {
    744                         if (!(primitive instanceof Way) || primitive.isDeleted()) {
    745                                 setEnabled(false);
    746                                 return;
    747                         }
    748                 }
    749                 setEnabled(selection.size() >= 2);
    750         }
     683    private Way getOld(Way r) {
     684        return getOld(r, oldWays);
     685    }*/
     686
     687    public static Way getOld(Way w, Map<Way, Way> oldWays) {
     688        if (oldWays.containsKey(w)) {
     689            return oldWays.get(w);
     690        } else {
     691            return w;
     692        }
     693    }
     694
     695    /**
     696    * Replies the set of referring relations
     697    *
     698    * @return the set of referring relations
     699    */
     700    private Set<Relation> getParentRelations(Collection<Way> ways) {
     701        Set<Relation> ret = new HashSet<>();
     702        for (Way w : ways) {
     703            ret.addAll(getParentRelations(w));
     704        }
     705        return ret;
     706    }
     707
     708    /** Enable this action only if something is selected */
     709    @Override
     710    protected void updateEnabledState() {
     711        if (getCurrentDataSet() == null) {
     712            setEnabled(false);
     713        } else {
     714            updateEnabledState(getCurrentDataSet().getSelected());
     715        }
     716    }
     717
     718    /** Enable this action only if something is selected */
     719    @Override
     720    protected void updateEnabledState(
     721            Collection<? extends OsmPrimitive> selection) {
     722        if (selection == null) {
     723            setEnabled(false);
     724            return;
     725        }
     726        for (OsmPrimitive primitive : selection) {
     727            if (!(primitive instanceof Way) || primitive.isDeleted()) {
     728                setEnabled(false);
     729                return;
     730            }
     731        }
     732        setEnabled(selection.size() >= 2);
     733    }
    751734}
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/MergeOverlapPlugin.java

    r29778 r30782  
    11package mergeoverlap;
    2 
    3 import static org.openstreetmap.josm.tools.I18n.tr;
    42
    53import org.openstreetmap.josm.Main;
     
    1311public class MergeOverlapPlugin extends Plugin {
    1412
    15     protected String name;
    16 
     13    /**
     14     * Constructs a new {@code MergeOverlapPlugin}.
     15     * @param info plugin information
     16     */
    1717    public MergeOverlapPlugin(PluginInformation info) {
    1818        super(info);
    19         name = tr("Merge overlap");
    2019        MainMenu.add(Main.main.menu.moreToolsMenu, new MergeOverlapAction());
    2120    }
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyCombinePrimitiveResolverDialog.java

    r30778 r30782  
    129129
    130130    public void buildRelationCorrespondance(Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
    131         getRelationMemberConflictResolverModel().buildRelationCorrespondance(targetPrimitive, newRelations, oldWays);
     131        getRelationMemberConflictResolverModel().buildRelationCorrespondance(targetPrimitive, newRelations, oldWays);
    132132    }
    133133}
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyRelationMemberConflictResolverModel.java

    r30766 r30782  
    5353    @Override
    5454    public void populate(Collection<Relation> relations, Collection<? extends OsmPrimitive> memberPrimitives) {
    55         throw new UnsupportedOperationException("Use populate(Collection<Relation>, Collection<? extends OsmPrimitive>, Map<Way, Way>) instead");
     55        throw new UnsupportedOperationException(
     56                "Use populate(Collection<Relation>, Collection<? extends OsmPrimitive>, Map<Way, Way>) instead");
    5657    }
    5758
     
    7879    @Override
    7980    protected Command buildResolveCommand(Relation relation, OsmPrimitive newPrimitive) {
    80         throw new UnsupportedOperationException("Use buildResolveCorrespondance(Relation, OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead");
     81        throw new UnsupportedOperationException(
     82                "Use buildResolveCorrespondance(Relation, OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead");
    8183    }
    8284
    83     protected void buildResolveCorrespondance(Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
     85    protected void buildResolveCorrespondance(
     86            Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
    8487
    85         List<RelationMember> relationsMembers = relation.getMembers();
    86         Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);
     88        List<RelationMember> relationsMembers = relation.getMembers();
     89        Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);
    8790        modifiedRelation.setMembers(null);
    8891        for (int i=0; i < relationsMembers.size(); i++) {
    89                 RelationMember rm = relationsMembers.get(i);
     92            RelationMember rm = relationsMembers.get(i);
    9093            RelationMemberConflictDecision decision = getDecision(relation, i);
    9194            if (decision == null) {
     
    9497                switch(decision.getDecision()) {
    9598                case KEEP:
    96                         if (newPrimitive instanceof Way) {
    97                         modifiedRelation.addMember(new RelationMember(decision.getRole(), MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));
    98                         }
    99                         else {
    100                                 modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
    101                         }
     99                    if (newPrimitive instanceof Way) {
     100                        modifiedRelation.addMember(new RelationMember(decision.getRole(),
     101                                MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));
     102                    } else {
     103                        modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
     104                    }
    102105                    break;
    103106                case REMOVE:
     
    114117    @Override
    115118    public List<Command> buildResolutionCommands(OsmPrimitive newPrimitive) {
    116         throw new UnsupportedOperationException("Use buildRelationCorrespondance(OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead");
     119        throw new UnsupportedOperationException(
     120                "Use buildRelationCorrespondance(OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead");
    117121    }
    118122
     
    125129    public void buildRelationCorrespondance(OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
    126130        for (Relation relation : relations) {
    127                 buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays);
     131            buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays);
    128132        }
    129133    }
Note: See TracChangeset for help on using the changeset viewer.