Ticket #19061: 19061.2.patch

File 19061.2.patch, 248.9 KB (added by taylor.smock, 4 years ago)

Making everything generic (still broken, but much further along)

  • src/org/openstreetmap/josm/actions/AlignInLineAction.java

     
    2525import org.openstreetmap.josm.data.osm.DataSet;
    2626import org.openstreetmap.josm.data.osm.Node;
    2727import org.openstreetmap.josm.data.osm.OsmPrimitive;
     28import org.openstreetmap.josm.data.osm.Relation;
    2829import org.openstreetmap.josm.data.osm.Way;
    2930import org.openstreetmap.josm.gui.Notification;
    3031import org.openstreetmap.josm.tools.Logging;
     
    172173            return;
    173174
    174175        try {
    175             Command cmd = buildCommand(getLayerManager().getEditDataSet());
     176            Command<OsmPrimitive, Node, Way, Relation> cmd = buildCommand(getLayerManager().getEditDataSet());
    176177            if (cmd != null) {
    177178                UndoRedoHandler.getInstance().add(cmd);
    178179            }
     
    191192     * @throws InvalidSelection if a polygon is selected, or if a node is used by 3 or more ways
    192193     * @since 13108
    193194     */
    194     public Command buildCommand(DataSet ds) throws InvalidSelection {
     195    public Command<OsmPrimitive, Node, Way, Relation> buildCommand(DataSet ds) throws InvalidSelection {
    195196        List<Node> selectedNodes = new ArrayList<>(ds.getSelectedNodes());
    196197        List<Way> selectedWays = new ArrayList<>(ds.getSelectedWays());
    197198        selectedWays.removeIf(w -> w.isIncomplete() || w.isEmpty());
     
    230231     * @return Command that perform action.
    231232     * @throws InvalidSelection If the nodes have same coordinates.
    232233     */
    233     private static Command alignOnlyNodes(List<Node> nodes) throws InvalidSelection {
     234    private static Command<OsmPrimitive, Node, Way, Relation> alignOnlyNodes(List<Node> nodes) throws InvalidSelection {
    234235        // Choose nodes used as anchor points for projection.
    235236        Node[] anchors = nodePairFurthestApart(nodes);
    236         Collection<Command> cmds = new ArrayList<>(nodes.size());
     237        Collection<Command<OsmPrimitive, Node, Way, Relation>> cmds = new ArrayList<>(nodes.size());
    237238        Line line = new Line(anchors[0], anchors[1]);
    238239        for (Node node: nodes) {
    239240            if (node != anchors[0] && node != anchors[1])
     
    248249     * @return Command that perform action
    249250     * @throws InvalidSelection if a polygon is selected, or if a node is used by 3 or more ways
    250251     */
    251     private static Command alignMultiWay(Collection<Way> ways) throws InvalidSelection {
     252    private static Command<OsmPrimitive, Node, Way, Relation> alignMultiWay(Collection<Way> ways) throws InvalidSelection {
    252253        // Collect all nodes and compute line equation
    253254        Set<Node> nodes = new HashSet<>();
    254255        Map<Way, Line> lines = new HashMap<>();
     
    263264        if (nodes.isEmpty()) {
    264265            throw new InvalidSelection(tr("Intersection of three or more ways can not be solved. Abort."));
    265266        }
    266         Collection<Command> cmds = new ArrayList<>(nodes.size());
     267        Collection<Command<OsmPrimitive, Node, Way, Relation>> cmds = new ArrayList<>(nodes.size());
    267268        List<Way> referers = new ArrayList<>(ways.size());
    268269        for (Node n: nodes) {
    269270            referers.clear();
     
    346347     * @return Command that perform action
    347348     * @throws InvalidSelection if more than 2 lines
    348349     */
    349     private static Command alignSingleNode(Node node, List<Line> lines) throws InvalidSelection {
     350    private static Command<OsmPrimitive, Node, Way, Relation> alignSingleNode(Node node, List<Line> lines) throws InvalidSelection {
    350351        if (lines.size() == 1)
    351352            return lines.get(0).projectionCommand(node);
    352353        else if (lines.size() == 2)
     
    404405         * @param n Node to be projected
    405406         * @return The command that do the projection of this node
    406407         */
    407         public Command projectionCommand(Node n) {
     408        public Command<OsmPrimitive, Node, Way, Relation> projectionCommand(Node n) {
    408409            double s = (xM - n.getEastNorth().getX()) * a + (yM - n.getEastNorth().getY()) * b;
    409             return new MoveCommand(n, a*s, b*s);
     410            return new MoveCommand<>(n, a*s, b*s);
    410411        }
    411412
    412413        /**
     
    416417         * @return The command that move the node
    417418         * @throws InvalidSelection if two parallels ways found
    418419         */
    419         public Command intersectionCommand(Node n, Line other) throws InvalidSelection {
     420        public Command<OsmPrimitive, Node, Way, Relation> intersectionCommand(Node n, Line other) throws InvalidSelection {
    420421            double d = this.a * other.b - other.a * this.b;
    421422            if (Math.abs(d) < 10e-6)
    422423                // parallels lines
     
    423424                throw new InvalidSelection(tr("Two parallels ways found. Abort."));
    424425            double x = (this.b * other.c - other.b * this.c) / d;
    425426            double y = (other.a * this.c - this.a * other.c) / d;
    426             return new MoveCommand(n, x - n.getEastNorth().getX(), y - n.getEastNorth().getY());
     427            return new MoveCommand<>(n, x - n.getEastNorth().getX(), y - n.getEastNorth().getY());
    427428        }
    428429    }
    429430
  • src/org/openstreetmap/josm/actions/CreateCircleAction.java

     
    2525import org.openstreetmap.josm.data.osm.DataSet;
    2626import org.openstreetmap.josm.data.osm.Node;
    2727import org.openstreetmap.josm.data.osm.OsmPrimitive;
     28import org.openstreetmap.josm.data.osm.Relation;
    2829import org.openstreetmap.josm.data.osm.Way;
    2930import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    3031import org.openstreetmap.josm.gui.Notification;
     
    199200                numberOfNodesInCircle >= nodes.size() ? (numberOfNodesInCircle - nodes.size()) : 0);
    200201
    201202        // now we can start doing things to OSM data
    202         Collection<Command> cmds = new LinkedList<>();
     203        Collection<Command<OsmPrimitive, Node, Way, Relation>> cmds = new LinkedList<>();
    203204
    204205        // build a way for the circle
    205206        List<Node> nodesToAdd = new ArrayList<>();
     
    219220                }
    220221                Node n = new Node(ll);
    221222                nodesToAdd.add(n);
    222                 cmds.add(new AddCommand(ds, n));
     223                cmds.add(new AddCommand<>(ds, n));
    223224            }
    224225        }
    225226        nodesToAdd.add(nodesToAdd.get(0)); // close the circle
     
    231232        if (existingWay == null) {
    232233            Way newWay = new Way();
    233234            newWay.setNodes(nodesToAdd);
    234             cmds.add(new AddCommand(ds, newWay));
     235            cmds.add(new AddCommand<>(ds, newWay));
    235236        } else {
    236237            Way newWay = new Way(existingWay);
    237238            newWay.setNodes(nodesToAdd);
    238             cmds.add(new ChangeCommand(ds, existingWay, newWay));
     239            cmds.add(new ChangeCommand<>(ds, existingWay, newWay));
    239240        }
    240241
    241242        UndoRedoHandler.getInstance().add(new SequenceCommand(tr("Create Circle"), cmds));
  • src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java

     
    3232import org.openstreetmap.josm.data.UndoRedoHandler;
    3333import org.openstreetmap.josm.data.osm.DataSet;
    3434import org.openstreetmap.josm.data.osm.IPrimitive;
     35import org.openstreetmap.josm.data.osm.Node;
    3536import org.openstreetmap.josm.data.osm.OsmPrimitive;
    3637import org.openstreetmap.josm.data.osm.OsmUtils;
    3738import org.openstreetmap.josm.data.osm.Relation;
     
    109110            if (commandAndRelation == null) {
    110111                return;
    111112            }
    112             final Command command = commandAndRelation.a;
     113            final Command<OsmPrimitive, Node, Way, Relation> command = commandAndRelation.a;
    113114            final Relation relation = commandAndRelation.b;
    114115
    115116            // to avoid EDT violations
     
    329330        final Relation existingRelation = rr.a;
    330331        final Relation relation = rr.b;
    331332
    332         final List<Command> list = removeTagsFromWaysIfNeeded(relation);
     333        final List<Command<OsmPrimitive, Node, Way, Relation>> list = removeTagsFromWaysIfNeeded(relation);
    333334        final String commandName;
    334335        if (existingRelation == null) {
    335             list.add(new AddCommand(selectedWays.iterator().next().getDataSet(), relation));
     336            list.add(new AddCommand<>(selectedWays.iterator().next().getDataSet(), relation));
    336337            commandName = getName(false);
    337338        } else {
    338339            if (!unchanged) {
    339                 list.add(new ChangeCommand(existingRelation, relation));
     340                list.add(new ChangeCommand<>(existingRelation, relation));
    340341            }
    341342            if (list.isEmpty()) {
    342343                if (unchanged) {
     
    388389     * @param relation the multipolygon style relation to process
    389390     * @return a list of commands to execute
    390391     */
    391     public static List<Command> removeTagsFromWaysIfNeeded(Relation relation) {
     392    public static List<Command<OsmPrimitive, Node, Way, Relation>> removeTagsFromWaysIfNeeded(Relation relation) {
    392393        Map<String, String> values = new HashMap<>(relation.getKeys());
    393394
    394395        List<Way> innerWays = new ArrayList<>();
     
    442443
    443444        values.put("area", OsmUtils.TRUE_VALUE);
    444445
    445         List<Command> commands = new ArrayList<>();
     446        List<Command<OsmPrimitive, Node, Way, Relation>> commands = new ArrayList<>();
    446447        boolean moveTags = Config.getPref().getBoolean("multipoly.movetags", true);
    447448
    448449        for (Entry<String, String> entry : values.entrySet()) {
     
    490491                if (ds == null) {
    491492                    ds = MainApplication.getLayerManager().getEditDataSet();
    492493                }
    493                 commands.add(new ChangeCommand(ds, relation, r2));
     494                commands.add(new ChangeCommand<>(ds, relation, r2));
    494495            }
    495496        }
    496497
  • src/org/openstreetmap/josm/actions/DeleteAction.java

     
    1515
    1616import org.openstreetmap.josm.command.DeleteCommand.DeletionCallback;
    1717import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     18import org.openstreetmap.josm.data.osm.IPrimitive;
     19import org.openstreetmap.josm.data.osm.IRelation;
    1820import org.openstreetmap.josm.data.osm.OsmPrimitive;
    19 import org.openstreetmap.josm.data.osm.Relation;
    2021import org.openstreetmap.josm.data.osm.RelationToChildReference;
    2122import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
    2223import org.openstreetmap.josm.gui.MainApplication;
     
    3738     */
    3839    public static final DeletionCallback defaultDeletionCallback = new DeletionCallback() {
    3940        @Override
    40         public boolean checkAndConfirmOutlyingDelete(Collection<? extends OsmPrimitive> primitives,
    41                 Collection<? extends OsmPrimitive> ignore) {
     41        public boolean checkAndConfirmOutlyingDelete(Collection<? extends IPrimitive> primitives,
     42                Collection<? extends IPrimitive> ignore) {
    4243            return DeleteAction.checkAndConfirmOutlyingDelete(primitives, ignore);
    4344        }
    4445
    4546        @Override
    46         public boolean confirmRelationDeletion(Collection<Relation> relations) {
     47        public boolean confirmRelationDeletion(Collection<? extends IRelation<?>> relations) {
    4748            return DeleteAction.confirmRelationDeletion(relations);
    4849        }
    4950
     
    9192     * @return true, if operating on outlying primitives is OK; false, otherwise
    9293     * @since 12749 (moved from DeleteCommand)
    9394     */
    94     public static boolean checkAndConfirmOutlyingDelete(Collection<? extends OsmPrimitive> primitives,
    95             Collection<? extends OsmPrimitive> ignore) {
     95    public static boolean checkAndConfirmOutlyingDelete(Collection<? extends IPrimitive> primitives,
     96            Collection<? extends IPrimitive> ignore) {
    9697        return checkAndConfirmOutlyingOperation("delete",
    9798                tr("Delete confirmation"),
    9899                tr("You are about to delete nodes outside of the area you have downloaded."
     
    113114     * @return {@code true} if user confirms the deletion
    114115     * @since 12760
    115116     */
    116     public static boolean confirmRelationDeletion(Collection<Relation> relations) {
     117    public static boolean confirmRelationDeletion(Collection<? extends IRelation<?>> relations) {
    117118        JPanel msg = new JPanel(new GridBagLayout());
    118119        msg.add(new JMultilineLabel("<html>" + trn(
    119120                "You are about to delete {0} relation: {1}"
  • src/org/openstreetmap/josm/actions/JoinAreasAction.java

     
    5757 */
    5858public class JoinAreasAction extends JosmAction {
    5959    // This will be used to commit commands and unite them into one large command sequence at the end
    60     private final transient LinkedList<Command> executedCmds = new LinkedList<>();
    61     private final transient LinkedList<Command> cmds = new LinkedList<>();
     60    private final transient LinkedList<Command<OsmPrimitive, Node, Way, Relation>> executedCmds = new LinkedList<>();
     61    private final transient LinkedList<Command<OsmPrimitive, Node, Way, Relation>> cmds = new LinkedList<>();
    6262    private DataSet ds;
    6363    private final transient List<Relation> addedRelations = new LinkedList<>();
    6464    private final boolean addUndoRedo;
     
    590590        cmds.clear();
    591591        if (!executedCmds.isEmpty()) {
    592592            // revert all executed commands
    593             ds = executedCmds.getFirst().getAffectedDataSet();
     593            ds = (DataSet) executedCmds.getFirst().getAffectedDataSet();
    594594            ds.update(() -> {
    595595                while (!executedCmds.isEmpty()) {
    596596                    executedCmds.removeLast().undoCommand();
     
    17401740    }
    17411741
    17421742    private static class JoinAreaCommand extends SequenceCommand {
    1743         JoinAreaCommand(Collection<Command> sequenz) {
     1743        JoinAreaCommand(Collection<Command<OsmPrimitive, Node, Way, Relation>> sequenz) {
    17441744            super(tr("Joined overlapping areas"), sequenz, true);
    17451745            setSequenceComplete(true);
    17461746        }
     
    17471747
    17481748        @Override
    17491749        public void undoCommand() {
    1750             getAffectedDataSet().update(super::undoCommand);
     1750            ((DataSet) getAffectedDataSet()).update(super::undoCommand);
    17511751        }
    17521752
    17531753        @Override
    17541754        public boolean executeCommand() {
    1755             return getAffectedDataSet().update(super::executeCommand);
     1755            return ((DataSet) getAffectedDataSet()).update(super::executeCommand);
    17561756        }
    17571757    }
    17581758}
  • src/org/openstreetmap/josm/actions/JoinNodeWayAction.java

     
    2929import org.openstreetmap.josm.data.UndoRedoHandler;
    3030import org.openstreetmap.josm.data.coor.EastNorth;
    3131import org.openstreetmap.josm.data.osm.DataSet;
     32import org.openstreetmap.josm.data.osm.IPrimitive;
    3233import org.openstreetmap.josm.data.osm.Node;
    3334import org.openstreetmap.josm.data.osm.OsmPrimitive;
     35import org.openstreetmap.josm.data.osm.Relation;
    3436import org.openstreetmap.josm.data.osm.Way;
    3537import org.openstreetmap.josm.data.osm.WaySegment;
    3638import org.openstreetmap.josm.data.projection.ProjectionRegistry;
     
    9294            return;
    9395        DataSet ds = getLayerManager().getEditDataSet();
    9496        Collection<Node> selectedNodes = ds.getSelectedNodes();
    95         Collection<Command> cmds = new LinkedList<>();
     97        Collection<Command<OsmPrimitive, Node, Way, Relation>> cmds = new LinkedList<>();
    9698        Map<Way, MultiMap<Integer, Node>> data = new LinkedHashMap<>();
    9799
    98100        // If the user has selected some ways, only join the node to these.
     
    101103        // Planning phase: decide where we'll insert the nodes and put it all in "data"
    102104        MapView mapView = MainApplication.getMap().mapView;
    103105        for (Node node : selectedNodes) {
    104             List<WaySegment> wss = mapView.getNearestWaySegments(mapView.getPoint(node), OsmPrimitive::isSelectable);
     106            List<WaySegment<Node, Way>> wss = mapView.getNearestWaySegments(mapView.getPoint(node), IPrimitive::isSelectable);
    105107            // we cannot trust the order of elements in wss because it was calculated based on rounded position value of node
    106             TreeMap<Double, List<WaySegment>> nearestMap = new TreeMap<>();
     108            TreeMap<Double, List<WaySegment<Node, Way>>> nearestMap = new TreeMap<>();
    107109            EastNorth en = node.getEastNorth();
    108             for (WaySegment ws : wss) {
     110            for (WaySegment<Node, Way> ws : wss) {
    109111                // Maybe cleaner to pass a "isSelected" predicate to getNearestWaySegments, but this is less invasive.
    110112                if (restrictToSelectedWays && !ws.way.isSelected()) {
    111113                    continue;
     
    119121                        ws.getSecondNode().getEastNorth(), en));
    120122                // resolution in numbers with large exponent not needed here..
    121123                distSq = Double.longBitsToDouble(Double.doubleToLongBits(distSq) >> 32 << 32);
    122                 List<WaySegment> wslist = nearestMap.computeIfAbsent(distSq, k -> new LinkedList<>());
     124                List<WaySegment<Node, Way>> wslist = nearestMap.computeIfAbsent(distSq, k -> new LinkedList<>());
    123125                wslist.add(ws);
    124126            }
    125127            Set<Way> seenWays = new HashSet<>();
    126128            Double usedDist = null;
    127129            while (!nearestMap.isEmpty()) {
    128                 Entry<Double, List<WaySegment>> entry = nearestMap.pollFirstEntry();
     130                Entry<Double, List<WaySegment<Node, Way>>> entry = nearestMap.pollFirstEntry();
    129131                if (usedDist != null) {
    130132                    double delta = entry.getKey() - usedDist;
    131133                    if (delta > 1e-4)
    132134                        break;
    133135                }
    134                 for (WaySegment ws : entry.getValue()) {
     136                for (WaySegment<Node, Way> ws : entry.getValue()) {
    135137                    // only use the closest WaySegment of each way and ignore those that already contain the node
    136138                    if (!ws.getFirstNode().equals(node) && !ws.getSecondNode().equals(node)
    137139                            && !seenWays.contains(ws.way)) {
     
    179181                            }
    180182                            continue;
    181183                        }
    182                         MoveCommand c = new MoveCommand(node,
     184                        MoveCommand<OsmPrimitive, Node, Way, Relation> c = new MoveCommand<>(node,
    183185                                ProjectionRegistry.getProjection().eastNorth2latlon(newPosition));
    184186                        cmds.add(c);
    185187                        movedNodes.put(node, newPosition);
     
    193195            }
    194196            Way wnew = new Way(w);
    195197            wnew.setNodes(wayNodes);
    196             cmds.add(new ChangeCommand(ds, w, wnew));
     198            cmds.add(new ChangeCommand<>(ds, w, wnew));
    197199        }
    198200
    199201        if (cmds.isEmpty()) return;
    200         UndoRedoHandler.getInstance().add(new SequenceCommand(getValue(NAME).toString(), cmds));
     202        UndoRedoHandler.getInstance().add(new SequenceCommand<>(getValue(NAME).toString(), cmds));
    201203    }
    202204
    203205    /**
  • src/org/openstreetmap/josm/actions/JosmAction.java

     
    1818import org.openstreetmap.josm.command.Command;
    1919import org.openstreetmap.josm.data.osm.DataSelectionListener;
    2020import org.openstreetmap.josm.data.osm.DataSet;
     21import org.openstreetmap.josm.data.osm.IPrimitive;
    2122import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2223import org.openstreetmap.josm.data.osm.OsmUtils;
    2324import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
     
    507508     */
    508509    public static boolean checkAndConfirmOutlyingOperation(String operation,
    509510            String dialogTitle, String outsideDialogMessage, String incompleteDialogMessage,
    510             Collection<? extends OsmPrimitive> primitives,
    511             Collection<? extends OsmPrimitive> ignore) {
     511            Collection<? extends IPrimitive> primitives,
     512            Collection<? extends IPrimitive> ignore) {
    512513        int checkRes = Command.checkOutlyingOrIncompleteOperation(primitives, ignore);
    513514        if ((checkRes & Command.IS_OUTSIDE) != 0) {
    514515            JPanel msg = new JPanel(new GridBagLayout());
  • src/org/openstreetmap/josm/actions/MergeNodesAction.java

     
    2929import org.openstreetmap.josm.data.coor.EastNorth;
    3030import org.openstreetmap.josm.data.coor.LatLon;
    3131import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     32import org.openstreetmap.josm.data.osm.INode;
     33import org.openstreetmap.josm.data.osm.IPrimitive;
    3234import org.openstreetmap.josm.data.osm.Node;
    3335import org.openstreetmap.josm.data.osm.OsmPrimitive;
    3436import org.openstreetmap.josm.data.osm.OsmUtils;
     
    4749import org.openstreetmap.josm.tools.Logging;
    4850import org.openstreetmap.josm.tools.Shortcut;
    4951import org.openstreetmap.josm.tools.UserCancelException;
     52import org.openstreetmap.josm.tools.Utils;
    5053
    5154/**
    5255 * Merges a collection of nodes into one node.
     
    8184
    8285        if (selectedNodes.size() == 1) {
    8386            MapView mapView = MainApplication.getMap().mapView;
    84             List<Node> nearestNodes = mapView.getNearestNodes(
    85                     mapView.getPoint(selectedNodes.get(0)), selectedNodes, OsmPrimitive::isUsable);
     87            List<INode> nearestNodes = mapView.getNearestNodes(
     88                    mapView.getPoint(selectedNodes.get(0)), new ArrayList<>(selectedNodes), IPrimitive::isUsable);
    8689            if (nearestNodes.isEmpty()) {
    8790                new Notification(
    8891                        tr("Please select at least two nodes to merge or one node that is close to another node."))
     
    9093                        .show();
    9194                return;
    9295            }
    93             selectedNodes.addAll(nearestNodes);
     96            nearestNodes.forEach(n -> selectedNodes.add((Node) n));
    9497        }
    9598
    9699        Node targetNode = selectTargetNode(selectedNodes);
     
    169172     * @param candidates the collection of candidate nodes
    170173     * @return the selected target node
    171174     */
    172     public static Node selectTargetNode(Collection<Node> candidates) {
    173         Node oldestNode = null;
    174         Node targetNode = null;
    175         Node lastNode = null;
    176         for (Node n : candidates) {
     175    public static <N extends INode> N selectTargetNode(Collection<N> candidates) {
     176        N oldestNode = null;
     177        N targetNode = null;
     178        N lastNode = null;
     179        for (N n : candidates) {
    177180            if (!n.isNew()) {
    178181                // Among existing nodes, try to keep the oldest used one
    179182                if (!n.getReferrers().isEmpty()) {
     
    292295     * @throws IllegalArgumentException if {@code layer} is null
    293296     * @since 12689
    294297     */
    295     public static Command mergeNodes(Collection<Node> nodes, Node targetLocationNode) {
     298    public static <N extends INode> Command<?, N, ?, ?> mergeNodes(Collection<N> nodes, N targetLocationNode) {
    296299        if (nodes == null) {
    297300            return null;
    298301        }
    299         Set<Node> allNodes = new HashSet<>(nodes);
     302        Set<N> allNodes = new HashSet<>(nodes);
    300303        allNodes.add(targetLocationNode);
    301         Node targetNode = selectTargetNode(allNodes);
     304        N targetNode = selectTargetNode(allNodes);
    302305        if (targetNode == null) {
    303306            return null;
    304307        }
     
    314317     * @return The command necessary to run in order to perform action, or {@code null} if there is nothing to do
    315318     * @throws IllegalArgumentException if layer is null
    316319     */
    317     public static Command mergeNodes(Collection<Node> nodes, Node targetNode, Node targetLocationNode) {
     320    public static <N extends INode> Command<?, N, ?, ?> mergeNodes(Collection<N> nodes, N targetNode, N targetLocationNode) {
    318321        CheckParameterUtil.ensureParameterNotNull(targetNode, "targetNode");
    319322        if (nodes == null) {
    320323            return null;
     
    325328
    326329            // the nodes we will have to delete
    327330            //
    328             Collection<Node> nodesToDelete = new HashSet<>(nodes);
     331            Collection<N> nodesToDelete = new HashSet<>(nodes);
    329332            nodesToDelete.remove(targetNode);
    330333
    331334            // fix the ways referring to at least one of the merged nodes
    332335            //
    333             List<Command> wayFixCommands = fixParentWays(nodesToDelete, targetNode);
     336            List<Command<?, N, ?, ?>> wayFixCommands = fixParentWays(nodesToDelete, targetNode);
    334337            if (wayFixCommands == null) {
    335338                return null;
    336339            }
    337             List<Command> cmds = new LinkedList<>(wayFixCommands);
     340            List<Command<?, N, ?, ?>> cmds = new LinkedList<>(wayFixCommands);
    338341
    339342            // build the commands
    340343            //
     
    341344            if (!targetNode.equals(targetLocationNode)) {
    342345                LatLon targetLocationCoor = targetLocationNode.getCoor();
    343346                if (!Objects.equals(targetNode.getCoor(), targetLocationCoor)) {
    344                     Node newTargetNode = new Node(targetNode);
     347                    N newTargetNode = Utils.clone(targetNode);
    345348                    newTargetNode.setCoor(targetLocationCoor);
    346                     cmds.add(new ChangeCommand(targetNode, newTargetNode));
     349                    cmds.add(new ChangeCommand<>(targetNode, newTargetNode));
    347350                }
    348351            }
    349352            cmds.addAll(CombinePrimitiveResolverDialog.launchIfNecessary(nodeTags, nodes, Collections.singleton(targetNode)));
    350353            if (!nodesToDelete.isEmpty()) {
    351                 cmds.add(new DeleteCommand(nodesToDelete));
     354                cmds.add(new DeleteCommand<>(nodesToDelete));
    352355            }
    353356            if (cmds.size() == 1)
    354357                return cmds.get(0);
  • src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

     
    1818import org.openstreetmap.josm.command.DeleteCommand;
    1919import org.openstreetmap.josm.data.UndoRedoHandler;
    2020import org.openstreetmap.josm.data.osm.DataSet;
    21 import org.openstreetmap.josm.data.osm.Node;
    22 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     21import org.openstreetmap.josm.data.osm.INode;
     22import org.openstreetmap.josm.data.osm.IPrimitive;
    2323import org.openstreetmap.josm.data.osm.Relation;
    2424import org.openstreetmap.josm.data.osm.WaySegment;
    2525import org.openstreetmap.josm.gui.MainApplication;
     
    9090
    9191    private static class DeleteParameters {
    9292        private DeleteMode mode;
    93         private Node nearestNode;
     93        private INode nearestNode;
    9494        private WaySegment nearestSegment;
    9595    }
    9696
     
    195195     * handles everything related to highlighting primitives and way
    196196     * segments for the given pointer position (via MouseEvent) and modifiers.
    197197     * @param e current mouse event
    198      * @param modifiers extended mouse modifiers, not necessarly taken from the given mouse event
     198     * @param modifiers extended mouse modifiers, not necessarily taken from the given mouse event
    199199     */
    200200    private void addHighlighting(MouseEvent e, int modifiers) {
    201201        if (!drawTargetHighlight)
     
    212212            // silent operation and SplitWayAction will show dialogs. A lot.
    213213            Command delCmd = buildDeleteCommands(e, modifiers, true);
    214214            // all other cases delete OsmPrimitives directly, so we can safely do the following
    215             repaintIfRequired(delCmd == null ? Collections.emptySet() : new HashSet<>(delCmd.getParticipatingPrimitives()), null);
     215            repaintIfRequired(delCmd == null ? Collections.emptySet() : new HashSet<IPrimitive>(delCmd.getParticipatingPrimitives()), null);
    216216        }
    217217    }
    218218
    219     private void repaintIfRequired(Set<OsmPrimitive> newHighlights, WaySegment newHighlightedWaySegment) {
     219    private void repaintIfRequired(Set<IPrimitive> newHighlights, WaySegment newHighlightedWaySegment) {
    220220        boolean needsRepaint = false;
    221221        OsmDataLayer editLayer = getLayerManager().getEditLayer();
    222222
     
    364364        DeleteParameters result = new DeleteParameters();
    365365
    366366        MapView mapView = MainApplication.getMap().mapView;
    367         result.nearestNode = mapView.getNearestNode(e.getPoint(), OsmPrimitive::isSelectable);
     367        result.nearestNode = mapView.getNearestNode(e.getPoint(), IPrimitive::isSelectable);
    368368        if (result.nearestNode == null) {
    369             result.nearestSegment = mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive::isSelectable);
     369            result.nearestSegment = mapView.getNearestWaySegment(e.getPoint(), IPrimitive::isSelectable);
    370370            if (result.nearestSegment != null) {
    371371                if (shift) {
    372372                    result.mode = DeleteMode.segment;
  • src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java

     
    3939import org.openstreetmap.josm.data.coor.EastNorth;
    4040import org.openstreetmap.josm.data.osm.DataIntegrityProblemException;
    4141import org.openstreetmap.josm.data.osm.DataSet;
     42import org.openstreetmap.josm.data.osm.INode;
     43import org.openstreetmap.josm.data.osm.IPrimitive;
     44import org.openstreetmap.josm.data.osm.IRelation;
     45import org.openstreetmap.josm.data.osm.IWay;
    4246import org.openstreetmap.josm.data.osm.Node;
    4347import org.openstreetmap.josm.data.osm.OsmPrimitive;
    4448import org.openstreetmap.josm.data.osm.Way;
     
    7882    private boolean nodeDragWithoutCtrl;
    7983
    8084    private long mouseDownTime;
    81     private transient WaySegment selectedSegment;
    82     private transient Node selectedNode;
     85    private transient WaySegment<INode, IWay<INode>> selectedSegment;
     86    private transient INode selectedNode;
    8387    private Color mainColor;
    8488    private transient Stroke mainStroke;
    8589
     
    106110    /**
    107111     * Collection of nodes that is moved
    108112     */
    109     private transient List<Node> movingNodeList;
     113    private transient List<INode> movingNodeList;
    110114
    111115    /**
    112116     * The direction that is currently active.
     
    141145    /**
    142146     * the command that performed last move.
    143147     */
    144     private transient MoveCommand moveCommand;
     148    private transient MoveCommand<?, ?, ?, ?> moveCommand;
    145149    /**
    146150     *  The command used for dual alignment movement.
    147151     *  Needs to be separate, due to two nodes moving in different directions.
    148152     */
    149     private transient MoveCommand moveCommand2;
     153    private transient MoveCommand<?, ?, ?, ?> moveCommand2;
    150154
    151155    /** The cursor for the 'create_new' mode. */
    152156    private final Cursor cursorCreateNew;
     
    392396        requestFocusInMapView();
    393397        updateKeyModifiers(e);
    394398
    395         selectedNode = map.mapView.getNearestNode(e.getPoint(), OsmPrimitive::isSelectable);
    396         selectedSegment = map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive::isSelectable);
     399        selectedNode = map.mapView.getNearestNode(e.getPoint(), IPrimitive::isSelectable);
     400        selectedSegment = map.mapView.getNearestWaySegment(e.getPoint(), IPrimitive::isSelectable);
    397401
    398402        // If nothing gets caught, stay in select mode
    399403        if (selectedSegment == null && selectedNode == null) return;
     
    488492                    // move nodes to new position
    489493                    if (moveCommand == null || moveCommand2 == null) {
    490494                        // make a new move commands
    491                         moveCommand = new MoveCommand(movingNodeList.get(0), movement1.getX(), movement1.getY());
    492                         moveCommand2 = new MoveCommand(movingNodeList.get(1), movement2.getX(), movement2.getY());
    493                         Command c = new SequenceCommand(tr("Extrude Way"), moveCommand, moveCommand2);
     495                        MoveCommand<IPrimitive, INode, IWay<INode>, IRelation<?>> tCommand = new MoveCommand<>(movingNodeList.get(0), movement1.getX(), movement1.getY());
     496                        MoveCommand<IPrimitive, INode, IWay<INode>, IRelation<?>> tCommand2 = new MoveCommand<>(movingNodeList.get(1), movement2.getX(), movement2.getY());
     497                        moveCommand = tCommand;
     498                        moveCommand2 = tCommand2;
     499                        Command<?, ?, ?, ?> c = new SequenceCommand<>(tr("Extrude Way"), tCommand, tCommand2);
    494500                        UndoRedoHandler.getInstance().add(c);
    495501                    } else {
    496502                        // reuse existing move commands
     
    505511                    //move nodes to new position
    506512                    if (moveCommand == null) {
    507513                        //make a new move command
    508                         moveCommand = new MoveCommand(new ArrayList<OsmPrimitive>(movingNodeList), bestMovement);
     514                        moveCommand = new MoveCommand<>(new ArrayList<IPrimitive>(movingNodeList), bestMovement);
    509515                        UndoRedoHandler.getInstance().add(moveCommand);
    510516                    } else {
    511517                        //reuse existing move command
  • src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java

     
    3535import org.openstreetmap.josm.data.osm.DataSet;
    3636import org.openstreetmap.josm.data.osm.Node;
    3737import org.openstreetmap.josm.data.osm.OsmPrimitive;
     38import org.openstreetmap.josm.data.osm.Relation;
    3839import org.openstreetmap.josm.data.osm.Way;
    3940import org.openstreetmap.josm.data.osm.WaySegment;
    4041import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
     
    8889
    8990    private transient Way targetWay;
    9091    private transient Node candidateNode;
    91     private transient WaySegment candidateSegment;
     92    private transient WaySegment<Node, Way> candidateSegment;
    9293
    9394    private Point mousePos;
    9495    private boolean dragging;
     
    437438
    438439            if (ctrl && !alt && candidateSegment != null) {
    439440                // Add a new node to the highlighted segment.
    440                 Collection<WaySegment> virtualSegments = new LinkedList<>();
     441                Collection<WaySegment<Node, Way>> virtualSegments = new LinkedList<>();
    441442
    442443                // Check if other ways have the same segment.
    443444                // We have to make sure that we add the new node to all of them.
     
    445446                commonParentWays.retainAll(candidateSegment.getSecondNode().getParentWays());
    446447                for (Way w : commonParentWays) {
    447448                    for (int i = 0; i < w.getNodesCount() - 1; i++) {
    448                         WaySegment testWS = new WaySegment(w, i);
     449                        WaySegment<Node, Way> testWS = new WaySegment<>(w, i);
    449450                        if (testWS.isSimilar(candidateSegment)) {
    450451                            virtualSegments.add(testWS);
    451452                        }
     
    452453                    }
    453454                }
    454455
    455                 Collection<Command> virtualCmds = new LinkedList<>();
     456                Collection<Command<OsmPrimitive, Node, Way, Relation>> virtualCmds = new LinkedList<>();
    456457                // Create the new node
    457458                Node virtualNode = new Node(mv.getEastNorth(mousePos.x, mousePos.y));
    458                 virtualCmds.add(new AddCommand(ds, virtualNode));
     459                virtualCmds.add(new AddCommand<>(ds, virtualNode));
    459460
    460461                // Adding the node to all segments found
    461                 for (WaySegment virtualSegment : virtualSegments) {
     462                for (WaySegment<Node, Way> virtualSegment : virtualSegments) {
    462463                    Way w = virtualSegment.way;
    463464                    Way wnew = new Way(w);
    464465                    wnew.addNode(virtualSegment.lowerIndex + 1, virtualNode);
    465                     virtualCmds.add(new ChangeCommand(w, wnew));
     466                    virtualCmds.add(new ChangeCommand<>(w, wnew));
    466467                }
    467468
    468469                // Finishing the sequence command
     
    485486                    nodes.remove(candidateNode);
    486487                    newWay.setNodes(nodes);
    487488                    if (nodes.size() < 2) {
    488                         final Command deleteCmd = DeleteCommand.delete(Collections.singleton(targetWay), true);
     489                        final Command<OsmPrimitive, Node, Way, Relation> deleteCmd = DeleteCommand.delete(Collections.singleton(targetWay), true);
    489490                        if (deleteCmd != null) {
    490491                            UndoRedoHandler.getInstance().add(deleteCmd);
    491492                        }
    492493                    } else {
    493                         UndoRedoHandler.getInstance().add(new ChangeCommand(targetWay, newWay));
     494                        UndoRedoHandler.getInstance().add(new ChangeCommand<>(targetWay, newWay));
    494495                    }
    495496                } else if (candidateNode.isTagged()) {
    496497                    JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
     
    497498                            tr("Cannot delete node that has tags"),
    498499                            tr("Error"), JOptionPane.ERROR_MESSAGE);
    499500                } else {
    500                     final Command deleteCmd = DeleteCommand.delete(Collections.singleton(candidateNode), true);
     501                    final Command<OsmPrimitive, Node, Way, Relation> deleteCmd = DeleteCommand.delete(Collections.singleton(candidateNode), true);
    501502                    if (deleteCmd != null) {
    502503                        UndoRedoHandler.getInstance().add(deleteCmd);
    503504                    }
     
    509510                EastNorth cursorEN = mv.getEastNorth(mousePos.x, mousePos.y);
    510511
    511512                UndoRedoHandler.getInstance().add(
    512                         new MoveCommand(candidateNode, cursorEN.east() - nodeEN.east(), cursorEN.north() - nodeEN.north()));
     513                        new MoveCommand<>(candidateNode, cursorEN.east() - nodeEN.east(), cursorEN.north() - nodeEN.north()));
    513514            }
    514515        }
    515516
  • src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyHelper.java

     
    66import java.util.List;
    77
    88import org.openstreetmap.josm.data.coor.EastNorth;
     9import org.openstreetmap.josm.data.osm.INode;
     10import org.openstreetmap.josm.data.osm.IPrimitive;
    911import org.openstreetmap.josm.data.osm.Node;
    10 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1112import org.openstreetmap.josm.data.osm.Way;
    1213import org.openstreetmap.josm.data.osm.WaySegment;
    1314import org.openstreetmap.josm.gui.MainApplication;
     
    4041            return null;
    4142        }
    4243
    43         Node node = mv.getNearestNode(p, OsmPrimitive::isSelectable);
     44        INode node = mv.getNearestNode(p, IPrimitive::isSelectable);
    4445        Way candidate = null;
    4546
    4647        if (node != null) {
    47             final Collection<OsmPrimitive> candidates = node.getReferrers();
    48             for (OsmPrimitive refferer : candidates) {
     48            final Collection<IPrimitive> candidates = (Collection<IPrimitive>) node.getReferrers();
     49            for (IPrimitive refferer : candidates) {
    4950                if (refferer instanceof Way) {
    5051                    candidate = (Way) refferer;
    5152                    break;
     
    5657            }
    5758        }
    5859
    59         return MainApplication.getMap().mapView.getNearestWay(p, OsmPrimitive::isSelectable);
     60        return MainApplication.getMap().mapView.getNearestWay(p, IPrimitive::isSelectable);
    6061    }
    6162
    6263    /**
     
    125126     * @param p the cursor position
    126127     * @return nearest way segment to cursor
    127128     */
    128     public static WaySegment findCandidateSegment(MapView mv, Way w, Point p) {
     129    public static WaySegment<Node, Way> findCandidateSegment(MapView mv, Way w, Point p) {
    129130        if (mv == null || w == null || p == null) {
    130131            return null;
    131132        }
     
    172173            }
    173174
    174175        }
    175         return candidate != -1 ? new WaySegment(w, candidate) : null;
     176        return candidate != -1 ? new WaySegment<Node, Way>(w, candidate) : null;
    176177    }
    177178}
  • src/org/openstreetmap/josm/actions/mapmode/SelectAction.java

     
    1111import java.awt.event.KeyEvent;
    1212import java.awt.event.MouseEvent;
    1313import java.awt.geom.Point2D;
     14import java.util.ArrayList;
    1415import java.util.Collection;
    1516import java.util.Collections;
    1617import java.util.HashSet;
     
    3233import org.openstreetmap.josm.data.UndoRedoHandler;
    3334import org.openstreetmap.josm.data.coor.EastNorth;
    3435import org.openstreetmap.josm.data.osm.DataSet;
     36import org.openstreetmap.josm.data.osm.INode;
     37import org.openstreetmap.josm.data.osm.IPrimitive;
     38import org.openstreetmap.josm.data.osm.IRelation;
     39import org.openstreetmap.josm.data.osm.IWay;
    3540import org.openstreetmap.josm.data.osm.Node;
    3641import org.openstreetmap.josm.data.osm.OsmData;
    3742import org.openstreetmap.josm.data.osm.OsmPrimitive;
     43import org.openstreetmap.josm.data.osm.Relation;
    3844import org.openstreetmap.josm.data.osm.Way;
    3945import org.openstreetmap.josm.data.osm.WaySegment;
    4046import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
     
    183189     * to remove the highlight from them again as otherwise the whole data
    184190     * set would have to be checked.
    185191     */
    186     private transient Optional<OsmPrimitive> currentHighlight = Optional.empty();
     192    private transient Optional<IPrimitive> currentHighlight = Optional.empty();
    187193
    188194    /**
    189195     * Create a new SelectAction
     
    257263     * @return {@code true} if repaint is required
    258264     */
    259265    private boolean giveUserFeedback(MouseEvent e, int modifiers) {
    260         Optional<OsmPrimitive> c = Optional.ofNullable(
     266        Optional<IPrimitive> c = Optional.ofNullable(
    261267                mv.getNearestNodeOrWay(e.getPoint(), mv.isSelectablePredicate, true));
    262268
    263269        updateKeyModifiersEx(modifiers);
    264270        determineMapMode(c.isPresent());
    265271
    266         Optional<OsmPrimitive> newHighlight = Optional.empty();
     272        Optional<IPrimitive> newHighlight = Optional.empty();
    267273
    268274        virtualManager.clear();
    269275        if (mode == Mode.MOVE && !dragInProgress() && virtualManager.activateVirtualNodeNearPoint(e.getPoint())) {
     
    300306     * @param nearbyStuff primitives near the cursor
    301307     * @return the cursor that should be displayed
    302308     */
    303     private Cursor getCursor(OsmPrimitive nearbyStuff) {
     309    private Cursor getCursor(IPrimitive nearbyStuff) {
    304310        String c = "rect";
    305311        switch(mode) {
    306312        case MOVE:
     
    308314                c = "virtual_node";
    309315                break;
    310316            }
    311             final OsmPrimitive osm = nearbyStuff;
     317            final IPrimitive osm = nearbyStuff;
    312318
    313319            if (dragInProgress()) {
    314320                // only consider merge if ctrl is pressed and there are nodes in
     
    319325                }
    320326                // only show merge to node cursor if nearby node and that node is currently
    321327                // not being dragged
    322                 final boolean hasTarget = osm instanceof Node && !osm.isSelected();
     328                final boolean hasTarget = osm instanceof INode && !osm.isSelected();
    323329                c = hasTarget ? "merge_to_node" : "merge";
    324330                break;
    325331            }
    326332
    327             c = (osm instanceof Node) ? "node" : c;
    328             c = (osm instanceof Way) ? "way" : c;
     333            c = (osm instanceof INode) ? "node" : c;
     334            c = (osm instanceof IWay) ? "way" : c;
    329335            if (shift) {
    330336                c += "_add";
    331337            } else if (ctrl) {
     
    369375        return true;
    370376    }
    371377
    372     private boolean repaintIfRequired(Optional<OsmPrimitive> newHighlight) {
     378    private boolean repaintIfRequired(Optional<IPrimitive> newHighlight) {
    373379        if (!drawTargetHighlight || currentHighlight.equals(newHighlight))
    374380            return false;
    375381        currentHighlight.ifPresent(osm -> osm.setHighlighted(false));
     
    413419
    414420        // primitives under cursor are stored in c collection
    415421
    416         OsmPrimitive nearestPrimitive = mv.getNearestNodeOrWay(e.getPoint(), mv.isSelectablePredicate, true);
     422        IPrimitive nearestPrimitive = mv.getNearestNodeOrWay(e.getPoint(), mv.isSelectablePredicate, true);
    417423
    418424        determineMapMode(nearestPrimitive != null);
    419425
     
    437443            if (!cancelDrawMode && nearestPrimitive instanceof Way) {
    438444                virtualManager.activateVirtualNodeNearPoint(e.getPoint());
    439445            }
    440             OsmPrimitive toSelect = cycleManager.cycleSetup(nearestPrimitive, e.getPoint());
     446            IPrimitive toSelect = cycleManager.cycleSetup(nearestPrimitive, e.getPoint());
    441447            selectPrims(asColl(toSelect), false, false);
    442448            useLastMoveCommandIfPossible();
    443449            // Schedule a timer to update status line "initialMoveDelay+1" ms in the future
     
    510516            // If ctrl is pressed we are in merge mode. Look for a nearby node,
    511517            // highlight it and adjust the cursor accordingly.
    512518            final boolean canMerge = ctrl && !getLayerManager().getEditDataSet().getSelectedNodes().isEmpty();
    513             final OsmPrimitive p = canMerge ? findNodeToMergeTo(e.getPoint()) : null;
     519            final IPrimitive p = canMerge ? findNodeToMergeTo(e.getPoint()) : null;
    514520            boolean needsRepaint = removeHighlighting();
    515521            if (p != null) {
    516522                p.setHighlighted(true);
     
    603609                    selectPrims(cycleManager.cyclePrims(), true, false);
    604610
    605611                    // If the user double-clicked a node, change to draw mode
    606                     Collection<OsmPrimitive> c = ds.getSelected();
    607                     if (e.getClickCount() >= 2 && c.size() == 1 && c.iterator().next() instanceof Node) {
     612                    Collection<IPrimitive> c = new ArrayList<>(ds.getSelected());
     613                    if (e.getClickCount() >= 2 && c.size() == 1 && c.iterator().next() instanceof INode) {
    608614                        // We need to do it like this as otherwise drawAction will see a double
    609615                        // click and switch back to SelectMode
    610616                        MainApplication.worker.execute(() -> map.selectDrawTool(true));
     
    698704        // Currently we support only transformations which do not affect relations.
    699705        // So don't add them in the first place to make handling easier
    700706        DataSet ds = getLayerManager().getEditDataSet();
    701         Collection<OsmPrimitive> selection = ds.getSelectedNodesAndWays();
     707        Collection<IPrimitive> selection = new ArrayList<>(ds.getSelectedNodesAndWays());
    702708        if (selection.isEmpty()) { // if nothing was selected to drag, just select nearest node/way to the cursor
    703709            ds.setSelected(mv.getNearestNodeOrWay(mv.getPoint(startEN), mv.isSelectablePredicate, true));
    704710        }
    705711
    706         Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
     712        Collection<INode> affectedNodes = new ArrayList<>(AllNodesVisitor.getAllNodes(selection));
    707713        // for these transformations, having only one node makes no sense - quit silently
    708714        if (affectedNodes.size() < 2 && (mode == Mode.ROTATE || mode == Mode.SCALE)) {
    709715            return false;
     
    721727                    moveCmd = new MoveCommand(selection, startEN, currentEN);
    722728                    UndoRedoHandler.getInstance().add(moveCmd);
    723729                }
    724                 for (Node n : affectedNodes) {
     730                for (INode n : affectedNodes) {
    725731                    if (n.isOutSideWorld()) {
    726732                        // Revert move
    727733                        if (moveCmd != null) {
     
    761767                    }
    762768                }
    763769
    764                 Collection<Way> ways = ds.getSelectedWays();
     770                Collection<IWay<?>> ways = new ArrayList<>(ds.getSelectedWays());
    765771                if (doesImpactStatusLine(affectedNodes, ways)) {
    766772                    MainApplication.getMap().statusLine.setDist(ways);
    767773                }
     774                Logging.getLastErrorAndWarnings();
    768775                return true;
    769776            });
    770777        }
    771778    }
    772779
    773     private static boolean doesImpactStatusLine(Collection<Node> affectedNodes, Collection<Way> selectedWays) {
    774         for (Way w : selectedWays) {
    775             for (Node n : w.getNodes()) {
     780    private static boolean doesImpactStatusLine(Collection<INode> affectedNodes, Collection<IWay<?>> selectedWays) {
     781        for (IWay<?> w : selectedWays) {
     782            for (INode n : w.getNodes()) {
    776783                if (affectedNodes.contains(n)) {
    777784                    return true;
    778785                }
     
    791798            return;
    792799        }
    793800        Command c = getLastCommandInDataset(dataSet);
    794         Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(dataSet.getSelected());
     801        Collection<? extends INode> affectedNodes = AllNodesVisitor.getAllNodes(dataSet.getSelected());
    795802        if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
    796803            // old command was created with different base point of movement, we need to recalculate it
    797804            ((MoveCommand) c).changeStartPoint(startEN);
     
    803810     * @param ds The data set the command needs to be in.
    804811     * @return last command
    805812     */
    806     private static Command getLastCommandInDataset(DataSet ds) {
    807         Command lastCommand = UndoRedoHandler.getInstance().getLastCommand();
     813    private static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> getLastCommandInDataset(OsmData<O, N, W, R> ds) {
     814        Command<O, N, W, R> lastCommand = UndoRedoHandler.getInstance().getLastCommand();
    808815        if (lastCommand instanceof SequenceCommand) {
    809             lastCommand = ((SequenceCommand) lastCommand).getLastCommand();
     816            lastCommand = (Command<O, N, W, R>) ((SequenceCommand) lastCommand).getLastCommand();
    810817        }
    811818        if (lastCommand != null && ds.equals(lastCommand.getAffectedDataSet())) {
    812819            return lastCommand;
     
    830837            ed.toggleEnable("movedHiddenElements");
    831838            showConfirmMoveDialog(ed);
    832839        }
    833         Set<Node> nodes = new HashSet<>();
     840        Set<INode> nodes = new HashSet<>();
    834841        int max = Config.getPref().getInt("warn.move.maxelements", 20);
    835         for (OsmPrimitive osm : getLayerManager().getEditDataSet().getSelected()) {
    836             if (osm instanceof Way) {
    837                 nodes.addAll(((Way) osm).getNodes());
    838             } else if (osm instanceof Node) {
    839                 nodes.add((Node) osm);
     842        for (IPrimitive osm : getLayerManager().getEditDataSet().getSelected()) {
     843            if (osm instanceof IWay) {
     844                nodes.addAll(((IWay<?>) osm).getNodes());
     845            } else if (osm instanceof INode) {
     846                nodes.add((INode) osm);
    840847            }
    841848            if (nodes.size() > max) {
    842849                break;
     
    875882    }
    876883
    877884    private boolean movesHiddenWay() {
    878         DataSet ds = getLayerManager().getEditDataSet();
    879         final Collection<Node> elementsToTest = new HashSet<>(ds.getSelectedNodes());
    880         for (Way osm : ds.getSelectedWays()) {
     885        DataSet ds = getLayerManager().getEditDataSet(); // TODO replace
     886        final Collection<INode> elementsToTest = new HashSet<>(ds.getSelectedNodes());
     887        for (IWay<?> osm : ds.getSelectedWays()) {
    881888            elementsToTest.addAll(osm.getNodes());
    882889        }
    883890        return elementsToTest.stream()
    884                 .flatMap(n -> n.referrers(Way.class))
    885                 .anyMatch(Way::isDisabledAndHidden);
     891                .flatMap(n -> n.getReferrers().stream().filter(IWay.class::isInstance).map(IWay.class::cast))
     892                .anyMatch(IWay::isDisabledAndHidden);
    886893    }
    887894
    888895    /**
     
    897904        if (selNodes.isEmpty())
    898905            return;
    899906
    900         Node target = findNodeToMergeTo(p);
     907        INode target = findNodeToMergeTo(p);
    901908        if (target == null)
    902909            return;
    903910
    904911        if (selNodes.size() == 1) {
    905912            // Move all selected primitive to preserve shape #10748
    906             Collection<OsmPrimitive> selection = ds.getSelectedNodesAndWays();
    907             Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
     913            Collection<IPrimitive> selection = new HashSet<>(ds.getSelectedNodesAndWays());
     914            Collection<INode> affectedNodes = AllNodesVisitor.getAllNodes(selection);
    908915            Command c = getLastCommandInDataset(ds);
    909916            ds.update(() -> {
    910917                if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
    911                     Node selectedNode = selNodes.iterator().next();
     918                    INode selectedNode = selNodes.iterator().next();
    912919                    EastNorth selectedEN = selectedNode.getEastNorth();
    913920                    EastNorth targetEN = target.getEastNorth();
    914921                    ((MoveCommand) c).moveAgain(targetEN.getX() - selectedEN.getX(),
     
    917924            });
    918925        }
    919926
    920         Collection<Node> nodesToMerge = new LinkedList<>(selNodes);
     927        Collection<INode> nodesToMerge = new LinkedList<>(selNodes);
    921928        nodesToMerge.add(target);
    922929        mergeNodes(MainApplication.getLayerManager().getEditLayer(), nodesToMerge, target);
    923930    }
     
    929936     * @param nodes the collection of nodes. Ignored if null
    930937     * @param targetLocationNode this node's location will be used for the target node
    931938     */
    932     public void mergeNodes(OsmDataLayer layer, Collection<Node> nodes,
    933                            Node targetLocationNode) {
     939    public void mergeNodes(OsmDataLayer layer, Collection<INode> nodes,
     940                           INode targetLocationNode) {
    934941        MergeNodesAction.doMergeNodes(layer, nodes, targetLocationNode);
    935942    }
    936943
     
    940947     * @param p mouse position
    941948     * @return node to merge to, or null
    942949     */
    943     private Node findNodeToMergeTo(Point p) {
    944         Collection<Node> target = mv.getNearestNodes(p,
    945                 getLayerManager().getEditDataSet().getSelectedNodes(),
     950    private INode findNodeToMergeTo(Point p) {
     951        Collection<INode> target = mv.getNearestNodes(p,
     952                new ArrayList<>(getLayerManager().getEditDataSet().getSelectedNodes()),
    946953                mv.isSelectablePredicate);
    947954        return target.isEmpty() ? null : target.iterator().next();
    948955    }
    949956
    950     private void selectPrims(Collection<OsmPrimitive> prims, boolean released, boolean area) {
    951         DataSet ds = getLayerManager().getActiveDataSet();
     957    private void selectPrims(Collection<IPrimitive> prims, boolean released, boolean area) {
     958        OsmData<?, ?, ?, ?> ds = getLayerManager().getActiveData();
    952959
    953960        // not allowed together: do not change dataset selection, return early
    954961        // Virtual Ways: if non-empty the cursor is above a virtual node. So don't highlight
     
    10271034    private final transient CycleManager cycleManager = new CycleManager();
    10281035    private final transient VirtualManager virtualManager = new VirtualManager();
    10291036
    1030     private class CycleManager {
     1037    private class CycleManager<T extends IPrimitive> {
    10311038
    1032         private Collection<OsmPrimitive> cycleList = Collections.emptyList();
     1039        private Collection<T> cycleList = Collections.emptyList();
    10331040        private boolean cyclePrims;
    1034         private OsmPrimitive cycleStart;
     1041        private IPrimitive cycleStart;
    10351042        private boolean waitForMouseUpParameter;
    10361043        private boolean multipleMatchesParameter;
    10371044        /**
     
    10481055         * @param p point where user clicked
    10491056         * @return OsmPrimitive to be selected
    10501057         */
    1051         private OsmPrimitive cycleSetup(OsmPrimitive nearest, Point p) {
    1052             OsmPrimitive osm = null;
     1058        private T cycleSetup(T nearest, Point p) {
     1059            T osm = null;
    10531060
    10541061            if (nearest != null) {
    10551062                osm = nearest;
     
    10701077                        cyclePrims = false;
    10711078
    10721079                        // find first already selected element in cycle list
    1073                         OsmPrimitive old = osm;
    1074                         for (OsmPrimitive o : cycleList) {
     1080                        T old = osm;
     1081                        for (T o : cycleList) {
    10751082                            if (o.isSelected()) {
    10761083                                cyclePrims = true;
    10771084                                osm = o;
     
    11051112         * <code>cycleList</code> field
    11061113         * @return the next element of cycle list
    11071114         */
    1108         private Collection<OsmPrimitive> cyclePrims() {
     1115        private Collection<IPrimitive> cyclePrims() {
    11091116            if (cycleList.size() <= 1) {
    11101117                // no real cycling, just return one-element collection with nearest primitive in it
    11111118                return cycleList;
     
    11131120            // updateKeyModifiers() already called before!
    11141121
    11151122            DataSet ds = getLayerManager().getActiveDataSet();
    1116             OsmPrimitive first = cycleList.iterator().next(), foundInDS = null;
    1117             OsmPrimitive nxt = first;
     1123            IPrimitive first = cycleList.iterator().next(), foundInDS = null;
     1124            IPrimitive nxt = first;
    11181125
    11191126            if (cyclePrims && shift) {
    1120                 for (Iterator<OsmPrimitive> i = cycleList.iterator(); i.hasNext();) {
     1127                for (Iterator<IPrimitive> i = cycleList.iterator(); i.hasNext();) {
    11211128                    nxt = i.next();
    11221129                    if (!nxt.isSelected()) {
    11231130                        break; // take first primitive in cycleList not in sel
     
    11251132                }
    11261133                // if primitives 1,2,3 are under cursor, [Alt-press] [Shift-release] gives 1 -> 12 -> 123
    11271134            } else {
    1128                 for (Iterator<OsmPrimitive> i = cycleList.iterator(); i.hasNext();) {
     1135                for (Iterator<IPrimitive> i = cycleList.iterator(); i.hasNext();) {
    11291136                    nxt = i.next();
    11301137                    if (nxt.isSelected()) {
    11311138                        foundInDS = nxt;
     
    11681175    private class VirtualManager {
    11691176
    11701177        private Node virtualNode;
    1171         private Collection<WaySegment> virtualWays = new LinkedList<>();
     1178        private Collection<WaySegment<?, ?>> virtualWays = new LinkedList<>();
    11721179        private int nodeVirtualSize;
    11731180        private int virtualSnapDistSq2;
    11741181        private int virtualSpace;
     
    11941201        private boolean activateVirtualNodeNearPoint(Point p) {
    11951202            if (nodeVirtualSize > 0) {
    11961203
    1197                 Collection<WaySegment> selVirtualWays = new LinkedList<>();
    1198                 Pair<Node, Node> vnp = null, wnp = new Pair<>(null, null);
     1204                Collection<WaySegment<?, ?>> selVirtualWays = new LinkedList<>();
     1205                Pair<INode, INode> vnp = null, wnp = new Pair<>(null, null);
    11991206
    1200                 for (WaySegment ws : mv.getNearestWaySegments(p, mv.isSelectablePredicate)) {
    1201                     Way w = ws.way;
     1207                for (WaySegment<?, ?> ws : mv.getNearestWaySegments(p, mv.isSelectablePredicate)) {
     1208                    IWay<?> w = ws.way;
    12021209
    12031210                    wnp.a = w.getNode(ws.lowerIndex);
    12041211                    wnp.b = w.getNode(ws.lowerIndex + 1);
     
    12371244            if (startEN == null) // #13724, #14712, #15087
    12381245                return;
    12391246            DataSet ds = getLayerManager().getEditDataSet();
    1240             Collection<Command> virtualCmds = new LinkedList<>();
    1241             virtualCmds.add(new AddCommand(ds, virtualNode));
    1242             for (WaySegment virtualWay : virtualWays) {
     1247            Collection<Command<OsmPrimitive, Node, Way, Relation>> virtualCmds = new LinkedList<>();
     1248            virtualCmds.add(new AddCommand<>(ds, virtualNode));
     1249            for (WaySegment<Node, Way> virtualWay : virtualWays) {
    12431250                Way w = virtualWay.way;
    12441251                Way wnew = new Way(w);
    12451252                wnew.addNode(virtualWay.lowerIndex + 1, virtualNode);
    1246                 virtualCmds.add(new ChangeCommand(ds, w, wnew));
     1253                virtualCmds.add(new ChangeCommand<>(ds, w, wnew));
    12471254            }
    1248             virtualCmds.add(new MoveCommand(ds, virtualNode, startEN, currentEN));
     1255            virtualCmds.add(new MoveCommand<>(ds, virtualNode, startEN, currentEN));
    12491256            String text = trn("Add and move a virtual new node to way",
    12501257                    "Add and move a virtual new node to {0} ways", virtualWays.size(),
    12511258                    virtualWays.size());
  • src/org/openstreetmap/josm/actions/relation/AddSelectionToRelations.java

     
    1515import org.openstreetmap.josm.data.UndoRedoHandler;
    1616import org.openstreetmap.josm.data.osm.DataSelectionListener;
    1717import org.openstreetmap.josm.data.osm.IPrimitive;
     18import org.openstreetmap.josm.data.osm.Node;
    1819import org.openstreetmap.josm.data.osm.OsmData;
     20import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1921import org.openstreetmap.josm.data.osm.OsmUtils;
    2022import org.openstreetmap.josm.data.osm.Relation;
     23import org.openstreetmap.josm.data.osm.Way;
    2124import org.openstreetmap.josm.gui.MainApplication;
    2225import org.openstreetmap.josm.gui.Notification;
    2326import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor;
     
    4043
    4144    @Override
    4245    public void actionPerformed(ActionEvent e) {
    43         Collection<Command> cmds = new LinkedList<>();
     46        Collection<Command<OsmPrimitive, Node, Way, Relation>> cmds = new LinkedList<>();
    4447        for (Relation orig : Utils.filteredCollection(relations, Relation.class)) {
    45             Command c = GenericRelationEditor.addPrimitivesToRelation(orig, MainApplication.getLayerManager().getActiveDataSet().getSelected());
     48            Command<OsmPrimitive, Node, Way, Relation> c = GenericRelationEditor.addPrimitivesToRelation(orig, MainApplication.getLayerManager().getActiveDataSet().getSelected());
    4649            if (c != null) {
    4750                cmds.add(c);
    4851            }
  • src/org/openstreetmap/josm/actions/upload/FixDataHook.java

     
    1616import org.openstreetmap.josm.command.SequenceCommand;
    1717import org.openstreetmap.josm.data.APIDataSet;
    1818import org.openstreetmap.josm.data.UndoRedoHandler;
     19import org.openstreetmap.josm.data.osm.Node;
    1920import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2021import org.openstreetmap.josm.data.osm.Relation;
     22import org.openstreetmap.josm.data.osm.Way;
    2123import org.openstreetmap.josm.spi.preferences.Config;
    2224import org.openstreetmap.josm.tools.Utils;
    2325
     
    187189    @Override
    188190    public boolean checkUpload(APIDataSet apiDataSet) {
    189191        if (Config.getPref().getBoolean("fix.data.on.upload", true)) {
    190             Collection<Command> cmds = new LinkedList<>();
     192            Collection<Command<OsmPrimitive, Node, Way, Relation>> cmds = new LinkedList<>();
    191193
    192194            for (OsmPrimitive osm : apiDataSet.getPrimitives()) {
    193195                Map<String, String> keys = new HashMap<>(osm.getKeys());
  • src/org/openstreetmap/josm/command/AbstractNodesCommand.java

     
    66
    77import javax.swing.Icon;
    88
    9 import org.openstreetmap.josm.data.osm.DataSet;
    10 import org.openstreetmap.josm.data.osm.Node;
    11 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     9import org.openstreetmap.josm.data.osm.INode;
     10import org.openstreetmap.josm.data.osm.IPrimitive;
     11import org.openstreetmap.josm.data.osm.IRelation;
     12import org.openstreetmap.josm.data.osm.IWay;
     13import org.openstreetmap.josm.data.osm.OsmData;
    1214import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    13 import org.openstreetmap.josm.data.osm.Way;
    1415import org.openstreetmap.josm.tools.ImageProvider;
    1516
    1617/**
    1718 * Abstracts superclass of {@link ChangeNodesCommand} / {@link RemoveNodesCommand}.
     19 * @param <O> the base type of primitives
     20 * @param <N> type representing nodes
     21 * @param <W> type representing ways
     22 * @param <R> type representing relations
    1823 * @param <C> type of nodes collection used for this command
    1924 * @since 15013
    2025 */
    21 public abstract class AbstractNodesCommand<C extends Collection<Node>> extends Command {
     26public abstract class AbstractNodesCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>, C extends Collection<N>> extends Command<O, N, W, R> {
    2227
    23     protected final Way way;
     28    protected final W way;
    2429    protected final C cmdNodes;
    2530
    2631    /**
     
    2833     * @param way The way to modify
    2934     * @param cmdNodes The collection of nodes for this command
    3035     */
    31     protected AbstractNodesCommand(Way way, C cmdNodes) {
     36    protected AbstractNodesCommand(W way, C cmdNodes) {
    3237        this(way.getDataSet(), way, cmdNodes);
    3338    }
    3439
     
    3843     * @param way The way to modify
    3944     * @param cmdNodes The collection of nodes for this command
    4045     */
    41     protected AbstractNodesCommand(DataSet ds, Way way, C cmdNodes) {
     46    protected AbstractNodesCommand(OsmData<O, N, W, R> ds, W way, C cmdNodes) {
    4247        super(ds);
    4348        this.way = Objects.requireNonNull(way, "way");
    4449        this.cmdNodes = Objects.requireNonNull(cmdNodes, "cmdNodes");
     
    5762        return true;
    5863    }
    5964
     65    @SuppressWarnings("unchecked")
    6066    @Override
    61     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    62         modified.add(way);
     67    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
     68        modified.add((O) way);
    6369    }
    6470
    6571    @Override
     
    7783        if (this == obj) return true;
    7884        if (obj == null || getClass() != obj.getClass()) return false;
    7985        if (!super.equals(obj)) return false;
    80         AbstractNodesCommand<?> that = (AbstractNodesCommand<?>) obj;
     86        AbstractNodesCommand<?, ?, ?, ?, ?> that = (AbstractNodesCommand<?, ?, ?, ?, ?>) obj;
    8187        return Objects.equals(way, that.way) &&
    8288               Objects.equals(cmdNodes, that.cmdNodes);
    8389    }
  • src/org/openstreetmap/josm/command/AddCommand.java

     
    1010
    1111import javax.swing.Icon;
    1212
    13 import org.openstreetmap.josm.data.osm.DataSet;
    1413import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    15 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     14import org.openstreetmap.josm.data.osm.INode;
     15import org.openstreetmap.josm.data.osm.IPrimitive;
     16import org.openstreetmap.josm.data.osm.IRelation;
     17import org.openstreetmap.josm.data.osm.IWay;
     18import org.openstreetmap.josm.data.osm.OsmData;
    1619import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1720import org.openstreetmap.josm.data.osm.Way;
    1821import org.openstreetmap.josm.tools.ImageProvider;
     
    2326 * See {@link ChangeCommand} for comments on relation back references.
    2427 *
    2528 * @author imi
     29 * @param <O> the base type of primitives
     30 * @param <N> type representing nodes
     31 * @param <W> type representing ways
     32 * @param <R> type representing relations
    2633 */
    27 public class AddCommand extends Command {
     34public class AddCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
    2835
    2936    /**
    3037     * The primitive to add to the dataset.
    3138     */
    32     private final OsmPrimitive osm;
     39    private final O osm;
    3340
    3441    /**
    3542     * Creates the command and specify the element to add in the context of the given data set.
     
    3744     * @param osm The primitive to add
    3845     * @since 11240
    3946     */
    40     public AddCommand(DataSet data, OsmPrimitive osm) {
     47    public AddCommand(OsmData<O, N, W, R> data, O osm) {
    4148        super(data);
    4249        this.osm = Objects.requireNonNull(osm, "osm");
    4350    }
    4451
    45     protected static final void checkNodeStyles(OsmPrimitive osm) {
     52    protected static final <O extends IPrimitive> void checkNodeStyles(O osm) {
    4653        if (osm instanceof Way) {
    4754            // Fix #10557 - node icon not updated after undoing/redoing addition of a way
    4855            ((Way) osm).clearCachedNodeStyles();
     
    6471    }
    6572
    6673    @Override
    67     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     74    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
    6875        added.add(osm);
    6976    }
    7077
     
    8693    }
    8794
    8895    @Override
    89     public Collection<OsmPrimitive> getParticipatingPrimitives() {
     96    public Collection<O> getParticipatingPrimitives() {
    9097        return Collections.singleton(osm);
    9198    }
    9299
     
    100107        if (this == obj) return true;
    101108        if (obj == null || getClass() != obj.getClass()) return false;
    102109        if (!super.equals(obj)) return false;
    103         AddCommand that = (AddCommand) obj;
     110        AddCommand<?, ?, ?, ?> that = (AddCommand<?, ?, ?, ?>) obj;
    104111        return Objects.equals(osm, that.osm);
    105112    }
    106113}
  • src/org/openstreetmap/josm/command/AddPrimitivesCommand.java

     
    1313
    1414import javax.swing.Icon;
    1515
    16 import org.openstreetmap.josm.data.osm.DataSet;
     16import org.openstreetmap.josm.data.osm.INode;
     17import org.openstreetmap.josm.data.osm.IPrimitive;
     18import org.openstreetmap.josm.data.osm.IRelation;
     19import org.openstreetmap.josm.data.osm.IWay;
    1720import org.openstreetmap.josm.data.osm.Node;
    1821import org.openstreetmap.josm.data.osm.NodeData;
     22import org.openstreetmap.josm.data.osm.OsmData;
    1923import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2024import org.openstreetmap.josm.data.osm.PrimitiveData;
    2125import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    2327
    2428/**
    2529 * Add primitives to a data layer.
     30 * @param <O> the base type of primitives
     31 * @param <N> type representing nodes
     32 * @param <W> type representing ways
     33 * @param <R> type representing relations
    2634 * @since 2305
    2735 */
    28 public class AddPrimitivesCommand extends Command {
     36public class AddPrimitivesCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
    2937
    3038    private List<PrimitiveData> data;
    3139    private Collection<PrimitiveData> toSelect;
     
    3240    private List<PrimitiveData> preExistingData;
    3341
    3442    // only filled on undo
    35     private List<OsmPrimitive> createdPrimitives;
     43    private List<O> createdPrimitives;
    3644
    3745    /**
    3846     * Constructs a new {@code AddPrimitivesCommand} to add data to the given data set.
     
    4149     * @param ds The target data set. Must not be {@code null}
    4250     * @since 12718
    4351     */
    44     public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, DataSet ds) {
     52    public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, OsmData<O, N, W, R> ds) {
    4553        super(ds);
    4654        init(data, toSelect);
    4755    }
     
    5260     * @param ds The target data set. Must not be {@code null}
    5361     * @since 12726
    5462     */
    55     public AddPrimitivesCommand(List<PrimitiveData> data, DataSet ds) {
     63    public AddPrimitivesCommand(List<PrimitiveData> data, OsmData<O, N, W, R> ds) {
    5664        this(data, data, ds);
    5765    }
    5866
     
    6876
    6977    @Override
    7078    public boolean executeCommand() {
    71         DataSet ds = getAffectedDataSet();
     79        OsmData<O, N, W, R> ds = getAffectedDataSet();
    7280        if (createdPrimitives == null) { // first time execution
    7381            List<OsmPrimitive> newPrimitives = new ArrayList<>(data.size());
    7482            preExistingData = new ArrayList<>();
    7583
    7684            for (PrimitiveData pd : data) {
    77                 OsmPrimitive primitive = ds.getPrimitiveById(pd);
     85                O primitive = ds.getPrimitiveById(pd);
    7886                boolean created = primitive == null;
    7987                if (primitive == null) {
    8088                    primitive = pd.getType().newInstance(pd.getUniqueId(), true);
     
    100108        } else { // redo
    101109            // When redoing this command, we have to add the same objects, otherwise
    102110            // a subsequent command (e.g. MoveCommand) cannot be redone.
    103             for (OsmPrimitive osm : createdPrimitives) {
     111            for (O osm : createdPrimitives) {
    104112                if (preExistingData.stream().anyMatch(pd -> pd.getUniqueId() == osm.getUniqueId())) {
    105113                    Optional<PrimitiveData> o = data.stream().filter(pd -> pd.getUniqueId() == osm.getUniqueId()).findAny();
    106114                    if (o.isPresent()) {
     
    118126    }
    119127
    120128    @Override public void undoCommand() {
    121         DataSet ds = getAffectedDataSet();
     129        OsmData<O, N, W, R> ds = getAffectedDataSet();
    122130        if (createdPrimitives == null) {
    123131            createdPrimitives = new ArrayList<>(data.size());
    124132            for (PrimitiveData pd : data) {
    125                 OsmPrimitive p = ds.getPrimitiveById(pd);
     133                O p = ds.getPrimitiveById(pd);
    126134                createdPrimitives.add(p);
    127135            }
    128136            createdPrimitives = PurgeCommand.topoSort(createdPrimitives);
    129137        }
    130         for (OsmPrimitive osm : createdPrimitives) {
     138        for (O osm : createdPrimitives) {
    131139            Optional<PrimitiveData> previous = preExistingData.stream().filter(pd -> pd.getUniqueId() == osm.getUniqueId()).findAny();
    132140            if (previous.isPresent()) {
    133141                osm.load(previous.get());
     
    149157    }
    150158
    151159    @Override
    152     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
    153             Collection<OsmPrimitive> added) {
     160    public void fillModifiedData(Collection<O> modified, Collection<O> deleted,
     161            Collection<O> added) {
    154162        // Does nothing because we don't want to create OsmPrimitives.
    155163    }
    156164
    157165    @Override
    158     public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
     166    public Collection<O> getParticipatingPrimitives() {
    159167        if (createdPrimitives != null)
    160168            return createdPrimitives;
    161169
    162         Collection<OsmPrimitive> prims = new HashSet<>();
     170        Collection<O> prims = new HashSet<>();
    163171        for (PrimitiveData d : data) {
    164172            prims.add(Optional.ofNullable(getAffectedDataSet().getPrimitiveById(d)).orElseThrow(
    165173                    () -> new JosmRuntimeException("No primitive found for " + d)));
     
    177185        if (this == obj) return true;
    178186        if (obj == null || getClass() != obj.getClass()) return false;
    179187        if (!super.equals(obj)) return false;
    180         AddPrimitivesCommand that = (AddPrimitivesCommand) obj;
     188        AddPrimitivesCommand<?, ?, ?, ?> that = (AddPrimitivesCommand<?, ?, ?, ?>) obj;
    181189        return Objects.equals(data, that.data) &&
    182190               Objects.equals(toSelect, that.toSelect) &&
    183191               Objects.equals(preExistingData, that.preExistingData) &&
  • src/org/openstreetmap/josm/command/ChangeCommand.java

     
    99
    1010import javax.swing.Icon;
    1111
    12 import org.openstreetmap.josm.data.osm.DataSet;
    1312import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    14 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     13import org.openstreetmap.josm.data.osm.INode;
     14import org.openstreetmap.josm.data.osm.IPrimitive;
     15import org.openstreetmap.josm.data.osm.IRelation;
     16import org.openstreetmap.josm.data.osm.IWay;
     17import org.openstreetmap.josm.data.osm.OsmData;
    1518import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1619import org.openstreetmap.josm.data.osm.Way;
    1720import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    1922
    2023/**
    2124 * Command that basically replaces one OSM primitive by another of the same type.
     25 * @param <O> the base type of primitives
     26 * @param <N> type representing nodes
     27 * @param <W> type representing ways
     28 * @param <R> type representing relations
    2229 *
    2330 * @since 93
    2431 */
    25 public class ChangeCommand extends Command {
     32public class ChangeCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
    2633
    27     private final OsmPrimitive osm;
    28     private final OsmPrimitive newOsm;
     34    private final O osm;
     35    private final O newOsm;
    2936
    3037    /**
    3138     * Constructs a new {@code ChangeCommand} in the context of {@code osm} data set.
     
    3340     * @param newOsm The new primitive
    3441     * @throws IllegalArgumentException if sanity checks fail
    3542     */
    36     public ChangeCommand(OsmPrimitive osm, OsmPrimitive newOsm) {
     43    public ChangeCommand(O osm, O newOsm) {
    3744        this(osm.getDataSet(), osm, newOsm);
    3845    }
    3946
     
    4552     * @throws IllegalArgumentException if sanity checks fail
    4653     * @since 11240
    4754     */
    48     public ChangeCommand(DataSet data, OsmPrimitive osm, OsmPrimitive newOsm) {
     55    public ChangeCommand(OsmData<O, N, W, R> data, O osm, O newOsm) {
    4956        super(data);
    5057        this.osm = osm;
    5158        this.newOsm = newOsm;
     
    7077    }
    7178
    7279    @Override
    73     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     80    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
    7481        modified.add(osm);
    7582    }
    7683
     
    96103     * @return the original OSM primitive to modify
    97104     * @since 14283
    98105     */
    99     public final OsmPrimitive getOsmPrimitive() {
     106    public final O getOsmPrimitive() {
    100107        return osm;
    101108    }
    102109
     
    105112     * @return the new OSM primitive
    106113     * @since 14283
    107114     */
    108     public final OsmPrimitive getNewOsmPrimitive() {
     115    public final O getNewOsmPrimitive() {
    109116        return newOsm;
    110117    }
    111118
     
    119126        if (this == obj) return true;
    120127        if (obj == null || getClass() != obj.getClass()) return false;
    121128        if (!super.equals(obj)) return false;
    122         ChangeCommand that = (ChangeCommand) obj;
     129        ChangeCommand<?, ?, ?, ?> that = (ChangeCommand<?, ?, ?, ?>) obj;
    123130        return Objects.equals(osm, that.osm) &&
    124131                Objects.equals(newOsm, that.newOsm);
    125132    }
  • src/org/openstreetmap/josm/command/ChangeNodesCommand.java

     
    55
    66import java.util.List;
    77
    8 import org.openstreetmap.josm.data.osm.DataSet;
    98import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    10 import org.openstreetmap.josm.data.osm.Node;
    11 import org.openstreetmap.josm.data.osm.Way;
     9import org.openstreetmap.josm.data.osm.INode;
     10import org.openstreetmap.josm.data.osm.IPrimitive;
     11import org.openstreetmap.josm.data.osm.IRelation;
     12import org.openstreetmap.josm.data.osm.IWay;
     13import org.openstreetmap.josm.data.osm.OsmData;
    1214
    1315/**
    1416 * Command that changes the nodes list of a way.
     
    1719 * tool of the validator, when processing large data sets.)
    1820 *
    1921 * @author Imi
     22 * @param <O> the base type of primitives
     23 * @param <N> type representing nodes
     24 * @param <W> type representing ways
     25 * @param <R> type representing relations
    2026 */
    21 public class ChangeNodesCommand extends AbstractNodesCommand<List<Node>> {
     27public class ChangeNodesCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends AbstractNodesCommand<O, N, W, R, List<N>> {
    2228
    2329    /**
    2430     * Constructs a new {@code ChangeNodesCommand}.
     
    2531     * @param way The way to modify
    2632     * @param newNodes The new list of nodes for the given way
    2733     */
    28     public ChangeNodesCommand(Way way, List<Node> newNodes) {
     34    public ChangeNodesCommand(W way, List<N> newNodes) {
    2935        super(way.getDataSet(), way, newNodes);
    3036    }
    3137
     
    3642     * @param newNodes The new list of nodes for the given way
    3743     * @since 12726
    3844     */
    39     public ChangeNodesCommand(DataSet ds, Way way, List<Node> newNodes) {
     45    public ChangeNodesCommand(OsmData<O, N, W, R> ds, W way, List<N> newNodes) {
    4046        super(ds, way, newNodes);
    4147    }
    4248
  • src/org/openstreetmap/josm/command/ChangePropertyCommand.java

     
    1818
    1919import org.openstreetmap.josm.data.osm.DataSet;
    2020import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     21import org.openstreetmap.josm.data.osm.Node;
    2122import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2223import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     24import org.openstreetmap.josm.data.osm.Relation;
     25import org.openstreetmap.josm.data.osm.Way;
    2326import org.openstreetmap.josm.tools.I18n;
    2427import org.openstreetmap.josm.tools.ImageProvider;
    2528
     
    3033 * @author imi
    3134 * @since 24
    3235 */
    33 public class ChangePropertyCommand extends Command {
     36public class ChangePropertyCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    3437
    3538    static final class OsmPseudoCommand implements PseudoCommand {
    3639        private final OsmPrimitive osm;
  • src/org/openstreetmap/josm/command/ChangePropertyKeyCommand.java

     
    1515import javax.swing.Icon;
    1616
    1717import org.openstreetmap.josm.data.osm.DataSet;
     18import org.openstreetmap.josm.data.osm.Node;
    1819import org.openstreetmap.josm.data.osm.OsmPrimitive;
     20import org.openstreetmap.josm.data.osm.Relation;
     21import org.openstreetmap.josm.data.osm.Way;
    1922import org.openstreetmap.josm.data.validation.util.NameVisitor;
    2023import org.openstreetmap.josm.tools.ImageProvider;
    2124
     
    2326 * Command that replaces the key of one or several objects
    2427 * @since 3669
    2528 */
    26 public class ChangePropertyKeyCommand extends Command {
     29public class ChangePropertyKeyCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    2730    static final class SinglePrimitivePseudoCommand implements PseudoCommand {
    2831        private final String name;
    2932        private final OsmPrimitive osm;
  • src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java

     
    1010
    1111import org.openstreetmap.josm.data.osm.DataSet;
    1212import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     13import org.openstreetmap.josm.data.osm.Node;
    1314import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1415import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1516import org.openstreetmap.josm.data.osm.Relation;
    1617import org.openstreetmap.josm.data.osm.RelationMember;
     18import org.openstreetmap.josm.data.osm.Way;
    1719import org.openstreetmap.josm.tools.ImageProvider;
    1820
    1921/**
     
    2123 *
    2224 * @author Teemu Koskinen &lt;teemu.koskinen@mbnet.fi&gt;
    2325 */
    24 public class ChangeRelationMemberRoleCommand extends Command {
     26public class ChangeRelationMemberRoleCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    2527
    2628    // The relation to be changed
    2729    private final Relation relation;
  • src/org/openstreetmap/josm/command/Command.java

     
    1212import org.openstreetmap.josm.data.coor.EastNorth;
    1313import org.openstreetmap.josm.data.coor.LatLon;
    1414import org.openstreetmap.josm.data.osm.DataSet;
     15import org.openstreetmap.josm.data.osm.INode;
     16import org.openstreetmap.josm.data.osm.IPrimitive;
     17import org.openstreetmap.josm.data.osm.IRelation;
     18import org.openstreetmap.josm.data.osm.IWay;
    1519import org.openstreetmap.josm.data.osm.Node;
     20import org.openstreetmap.josm.data.osm.OsmData;
    1621import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1722import org.openstreetmap.josm.data.osm.PrimitiveData;
    18 import org.openstreetmap.josm.data.osm.Relation;
    19 import org.openstreetmap.josm.data.osm.Way;
    20 import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;
     23import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
    2124import org.openstreetmap.josm.tools.CheckParameterUtil;
    2225
    2326/**
     
    2730 * The command remembers the {@link DataSet} it is operating on.
    2831 *
    2932 * @author imi
     33 * @param <O> the base type of primitives
     34 * @param <N> type representing nodes
     35 * @param <W> type representing ways
     36 * @param <R> type representing relations
    3037 * @since 21 (creation)
    3138 * @since 10599 (signature)
    3239 */
    33 public abstract class Command implements PseudoCommand {
     40public abstract class Command<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> implements PseudoCommand {
    3441
    3542    /** IS_OK : operation is okay */
    3643    public static final int IS_OK = 0;
     
    3946    /** IS_INCOMPLETE: operation on incomplete target */
    4047    public static final int IS_INCOMPLETE = 2;
    4148
    42     private static final class CloneVisitor implements OsmPrimitiveVisitor {
    43         final Map<OsmPrimitive, PrimitiveData> orig = new LinkedHashMap<>();
     49    private static final class CloneVisitor<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> implements PrimitiveVisitor<N, W, R> {
     50        final Map<O, PrimitiveData> orig = new LinkedHashMap<>();
    4451
    4552        @Override
    46         public void visit(Node n) {
     53        public void visit(N n) {
    4754            orig.put(n, n.save());
    4855        }
    4956
    5057        @Override
    51         public void visit(Way w) {
     58        public void visit(W w) {
    5259            orig.put(w, w.save());
    5360        }
    5461
    5562        @Override
    56         public void visit(Relation e) {
     63        public void visit(R e) {
    5764            orig.put(e, e.save());
    5865        }
    5966    }
     
    7178         * Constructs a new {@code OldNodeState} for the given node.
    7279         * @param node The node whose state has to be remembered
    7380         */
    74         public OldNodeState(Node node) {
     81        public OldNodeState(INode node) {
    7582            latLon = node.getCoor();
    7683            eastNorth = node.getEastNorth();
    7784            modified = node.isModified();
     
    122129    }
    123130
    124131    /** the map of OsmPrimitives in the original state to OsmPrimitives in cloned state */
    125     private Map<OsmPrimitive, PrimitiveData> cloneMap = new HashMap<>();
     132    private Map<O, PrimitiveData> cloneMap = new HashMap<>();
    126133
    127134    /** the dataset which this command is applied to */
    128     private final DataSet data;
     135    private final OsmData<O, N, W, R> data;
    129136
    130137    /**
    131138     * Creates a new command in the context of a specific data set, without data layer
     
    134141     * @throws IllegalArgumentException if data is null
    135142     * @since 11240
    136143     */
    137     public Command(DataSet data) {
     144    public Command(OsmData<O, N, W, R> data) {
    138145        CheckParameterUtil.ensureParameterNotNull(data, "data");
    139146        this.data = data;
    140147    }
     
    147154     * @return true
    148155     */
    149156    public boolean executeCommand() {
    150         CloneVisitor visitor = new CloneVisitor();
    151         Collection<OsmPrimitive> all = new ArrayList<>();
     157        CloneVisitor<O, N, W, R> visitor = new CloneVisitor<>();
     158        Collection<O> all = new ArrayList<>();
    152159        fillModifiedData(all, all, all);
    153         for (OsmPrimitive osm : all) {
     160        for (O osm : all) {
    154161            osm.accept(visitor);
    155162        }
    156163        cloneMap = visitor.orig;
     
    165172     * This implementation undoes all objects stored by a former call to executeCommand.
    166173     */
    167174    public void undoCommand() {
    168         for (Entry<OsmPrimitive, PrimitiveData> e : cloneMap.entrySet()) {
    169             OsmPrimitive primitive = e.getKey();
     175        for (Entry<O, PrimitiveData> e : cloneMap.entrySet()) {
     176            O primitive = e.getKey();
    170177            if (primitive.getDataSet() != null) {
    171178                e.getKey().load(e.getValue());
    172179            }
     
    188195     * @return The data set. May be <code>null</code> if no layer was set and no edit layer was found.
    189196     * @since 10467
    190197     */
    191     public DataSet getAffectedDataSet() {
     198    public OsmData<O, N, W, R> getAffectedDataSet() {
    192199        return data;
    193200    }
    194201
     
    200207     * @param deleted The deleted primitives
    201208     * @param added The added primitives
    202209     */
    203     public abstract void fillModifiedData(Collection<OsmPrimitive> modified,
    204             Collection<OsmPrimitive> deleted,
    205             Collection<OsmPrimitive> added);
     210    public abstract void fillModifiedData(Collection<O> modified,
     211            Collection<O> deleted,
     212            Collection<O> added);
    206213
    207214    /**
    208215     * Return the primitives that take part in this command.
     
    209216     * The collection is computed during execution.
    210217     */
    211218    @Override
    212     public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
     219    public Collection<? extends O> getParticipatingPrimitives() {
    213220        return cloneMap.keySet();
    214221    }
    215222
     
    221228     * @return true, if operating on outlying primitives is OK; false, otherwise
    222229     */
    223230    public static int checkOutlyingOrIncompleteOperation(
    224             Collection<? extends OsmPrimitive> primitives,
    225             Collection<? extends OsmPrimitive> ignore) {
     231            Collection<? extends IPrimitive> primitives,
     232            Collection<? extends IPrimitive> ignore) {
    226233        int res = 0;
    227         for (OsmPrimitive osm : primitives) {
     234        for (IPrimitive osm : primitives) {
    228235            if (osm.isIncomplete()) {
    229236                res |= IS_INCOMPLETE;
    230             } else if (osm.isOutsideDownloadArea()
     237            } else if (osm instanceof OsmPrimitive && ((OsmPrimitive) osm).isOutsideDownloadArea()
    231238                    && (ignore == null || !ignore.contains(osm))) {
    232239                res |= IS_OUTSIDE;
    233240            }
     
    242249     * @throws AssertionError if no {@link DataSet} is set or if any primitive does not belong to that dataset.
    243250     */
    244251    protected void ensurePrimitivesAreInDataset() {
    245         for (OsmPrimitive primitive : this.getParticipatingPrimitives()) {
     252        for (IPrimitive primitive : this.getParticipatingPrimitives()) {
    246253            if (primitive.getDataSet() != this.getAffectedDataSet()) {
    247254                throw new AssertionError("Primitive is of wrong data set for this command: " + primitive);
    248255            }
     
    258265    public boolean equals(Object obj) {
    259266        if (this == obj) return true;
    260267        if (obj == null || getClass() != obj.getClass()) return false;
    261         Command command = (Command) obj;
     268        Command<?, ?, ?, ?> command = (Command<?, ?, ?, ?>) obj;
    262269        return Objects.equals(cloneMap, command.cloneMap) &&
    263270               Objects.equals(data, command.data);
    264271    }
  • src/org/openstreetmap/josm/command/DeleteCommand.java

     
    2222
    2323import javax.swing.Icon;
    2424
    25 import org.openstreetmap.josm.data.osm.DataSet;
    2625import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    27 import org.openstreetmap.josm.data.osm.Node;
     26import org.openstreetmap.josm.data.osm.INode;
     27import org.openstreetmap.josm.data.osm.IPrimitive;
     28import org.openstreetmap.josm.data.osm.IRelation;
     29import org.openstreetmap.josm.data.osm.IWay;
     30import org.openstreetmap.josm.data.osm.OsmData;
    2831import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2932import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    3033import org.openstreetmap.josm.data.osm.PrimitiveData;
    31 import org.openstreetmap.josm.data.osm.Relation;
    3234import org.openstreetmap.josm.data.osm.RelationToChildReference;
    33 import org.openstreetmap.josm.data.osm.Way;
    3435import org.openstreetmap.josm.data.osm.WaySegment;
    3536import org.openstreetmap.josm.tools.CheckParameterUtil;
    3637import org.openstreetmap.josm.tools.ImageProvider;
     
    4041 * A command to delete a number of primitives from the dataset.
    4142 * To be used correctly, this class requires an initial call to {@link #setDeletionCallback(DeletionCallback)} to
    4243 * allow interactive confirmation actions.
     44 * @param <O> the base type of primitives
     45 * @param <N> type representing nodes
     46 * @param <W> type representing ways
     47 * @param <R> type representing relations
    4348 * @since 23
    4449 */
    45 public class DeleteCommand extends Command {
     50public class DeleteCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
    4651    private static final class DeleteChildCommand implements PseudoCommand {
    47         private final OsmPrimitive osm;
     52        private final IPrimitive osm;
    4853
    49         private DeleteChildCommand(OsmPrimitive osm) {
     54        private DeleteChildCommand(IPrimitive osm) {
    5055            this.osm = osm;
    5156        }
    5257
     
    6166        }
    6267
    6368        @Override
    64         public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
     69        public Collection<? extends IPrimitive> getParticipatingPrimitives() {
    6570            return Collections.singleton(osm);
    6671        }
    6772
     
    8388         * @param ignore {@code null} or a primitive to be ignored
    8489         * @return true, if operating on outlying primitives is OK; false, otherwise
    8590         */
    86         boolean checkAndConfirmOutlyingDelete(Collection<? extends OsmPrimitive> primitives, Collection<? extends OsmPrimitive> ignore);
     91        boolean checkAndConfirmOutlyingDelete(Collection<? extends IPrimitive> primitives, Collection<? extends IPrimitive> ignore);
    8792
    8893        /**
    8994         * Confirm before deleting a relation, as it is a common newbie error.
     
    9196         * @return {@code true} if user confirms the deletion
    9297         * @since 12760
    9398         */
    94         boolean confirmRelationDeletion(Collection<Relation> relations);
     99        boolean confirmRelationDeletion(Collection<? extends IRelation<?>> relations);
    95100
    96101        /**
    97102         * Confirm before removing a collection of primitives from their parent relations.
     
    117122    /**
    118123     * The primitives that get deleted.
    119124     */
    120     private final Collection<? extends OsmPrimitive> toDelete;
    121     private final Map<OsmPrimitive, PrimitiveData> clonedPrimitives = new HashMap<>();
     125    private final Collection<O> toDelete;
     126    private final Map<O, PrimitiveData> clonedPrimitives = new HashMap<>();
    122127
    123128    /**
    124129     * Constructor. Deletes a collection of primitives in the current edit layer.
     
    126131     * @param data the primitives to delete. Must neither be null nor empty, and belong to a data set
    127132     * @throws IllegalArgumentException if data is null or empty
    128133     */
    129     public DeleteCommand(Collection<? extends OsmPrimitive> data) {
     134    public DeleteCommand(Collection<? extends O> data) {
    130135        this(data.iterator().next().getDataSet(), data);
    131136    }
    132137
     
    136141     * @param data  the primitive to delete. Must not be null.
    137142     * @throws IllegalArgumentException if data is null
    138143     */
    139     public DeleteCommand(OsmPrimitive data) {
     144    public DeleteCommand(O data) {
    140145        this(Collections.singleton(data));
    141146    }
    142147
     
    149154     * @throws IllegalArgumentException if layer is null
    150155     * @since 12718
    151156     */
    152     public DeleteCommand(DataSet dataset, OsmPrimitive data) {
     157    public DeleteCommand(OsmData<O, N, W, R> dataset, O data) {
    153158        this(dataset, Collections.singleton(data));
    154159    }
    155160
     
    162167     * @throws IllegalArgumentException if data is null or empty
    163168     * @since 11240
    164169     */
    165     public DeleteCommand(DataSet dataset, Collection<? extends OsmPrimitive> data) {
     170    public DeleteCommand(OsmData<O, N, W, R> dataset, Collection<? extends O> data) {
    166171        super(dataset);
    167172        CheckParameterUtil.ensureParameterNotNull(data, "data");
    168         this.toDelete = data;
     173        this.toDelete = new HashSet<>(data);
    169174        checkConsistency();
    170175    }
    171176
     
    173178        if (toDelete.isEmpty()) {
    174179            throw new IllegalArgumentException(tr("At least one object to delete required, got empty collection"));
    175180        }
    176         for (OsmPrimitive p : toDelete) {
     181        for (O p : toDelete) {
    177182            if (p == null) {
    178183                throw new IllegalArgumentException("Primitive to delete must not be null");
    179184            } else if (p.getDataSet() == null) {
     
    186191    public boolean executeCommand() {
    187192        ensurePrimitivesAreInDataset();
    188193        // Make copy and remove all references (to prevent inconsistent dataset (delete referenced) while command is executed)
    189         for (OsmPrimitive osm: toDelete) {
     194        for (O osm: toDelete) {
    190195            if (osm.isDeleted())
    191196                throw new IllegalArgumentException(osm + " is already deleted");
    192197            clonedPrimitives.put(osm, osm.save());
    193198
    194             if (osm instanceof Way) {
    195                 ((Way) osm).setNodes(null);
    196             } else if (osm instanceof Relation) {
    197                 ((Relation) osm).setMembers(null);
     199            if (osm instanceof IWay<?>) {
     200                ((IWay<?>) osm).setNodes(null);
     201            } else if (osm instanceof IRelation<?>) {
     202                ((IRelation<?>) osm).setMembers(null);
    198203            }
    199204        }
    200205
    201         for (OsmPrimitive osm: toDelete) {
     206        for (O osm: toDelete) {
    202207            osm.setDeleted(true);
    203208        }
    204209
     
    209214    public void undoCommand() {
    210215        ensurePrimitivesAreInDataset();
    211216
    212         for (OsmPrimitive osm: toDelete) {
     217        for (O osm: toDelete) {
    213218            osm.setDeleted(false);
    214219        }
    215220
    216         for (Entry<OsmPrimitive, PrimitiveData> entry: clonedPrimitives.entrySet()) {
     221        for (Entry<O, PrimitiveData> entry: clonedPrimitives.entrySet()) {
    217222            entry.getKey().load(entry.getValue());
    218223        }
    219224    }
    220225
    221226    @Override
    222     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     227    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
    223228        // Do nothing
    224229    }
    225230
    226231    private EnumSet<OsmPrimitiveType> getTypesToDelete() {
    227232        EnumSet<OsmPrimitiveType> typesToDelete = EnumSet.noneOf(OsmPrimitiveType.class);
    228         for (OsmPrimitive osm : toDelete) {
     233        for (O osm : toDelete) {
    229234            typesToDelete.add(OsmPrimitiveType.from(osm));
    230235        }
    231236        return typesToDelete;
     
    234239    @Override
    235240    public String getDescriptionText() {
    236241        if (toDelete.size() == 1) {
    237             OsmPrimitive primitive = toDelete.iterator().next();
     242            O primitive = toDelete.iterator().next();
    238243            String msg;
    239244            switch(OsmPrimitiveType.from(primitive)) {
    240245            case NODE: msg = marktr("Delete node {0}"); break;
     
    278283            return null;
    279284        else {
    280285            List<PseudoCommand> children = new ArrayList<>(toDelete.size());
    281             for (final OsmPrimitive osm : toDelete) {
     286            for (final O osm : toDelete) {
    282287                children.add(new DeleteChildCommand(osm));
    283288            }
    284289            return children;
     
    286291        }
    287292    }
    288293
    289     @Override public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
     294    @Override public Collection<O> getParticipatingPrimitives() {
    290295        return toDelete;
    291296    }
    292297
     
    303308     * @throws IllegalArgumentException if layer is null
    304309     * @since 12718
    305310     */
    306     public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection, boolean silent) {
     311    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> deleteWithReferences(Collection<O> selection, boolean silent) {
    307312        if (selection == null || selection.isEmpty()) return null;
    308         Set<OsmPrimitive> parents = OsmPrimitive.getReferrer(selection);
     313        Set<O> parents = OsmPrimitive.getReferrer(selection);
    309314        parents.addAll(selection);
    310315
    311316        if (parents.isEmpty())
     
    312317            return null;
    313318        if (!silent && !callback.checkAndConfirmOutlyingDelete(parents, null))
    314319            return null;
    315         return new DeleteCommand(parents.iterator().next().getDataSet(), parents);
     320        return new DeleteCommand<>(parents.iterator().next().getDataSet(), parents);
    316321    }
    317322
    318323    /**
     
    327332     * @throws IllegalArgumentException if layer is null
    328333     * @since 12718
    329334     */
    330     public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
     335    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> deleteWithReferences(Collection<? extends O> selection) {
    331336        return deleteWithReferences(selection, false);
    332337    }
    333338
     
    344349     * @return command a command to perform the deletions, or null if there is nothing to delete.
    345350     * @since 12718
    346351     */
    347     public static Command delete(Collection<? extends OsmPrimitive> selection) {
     352    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> delete(Collection<O> selection) {
    348353        return delete(selection, true, false);
    349354    }
    350355
     
    359364     * @return the collection of nodes referred to by primitives in <code>primitivesToDelete</code> which
    360365     * can be deleted too
    361366     */
    362     protected static Collection<Node> computeNodesToDelete(Collection<OsmPrimitive> primitivesToDelete) {
    363         Collection<Node> nodesToDelete = new HashSet<>();
    364         for (Way way : Utils.filteredCollection(primitivesToDelete, Way.class)) {
    365             for (Node n : way.getNodes()) {
     367    protected static Collection<INode> computeNodesToDelete(Collection<IPrimitive> primitivesToDelete) {
     368        Collection<INode> nodesToDelete = new HashSet<>();
     369        for (IWay<?> way : Utils.filteredCollection(primitivesToDelete, IWay.class)) {
     370            for (INode n : way.getNodes()) {
    366371                if (n.isTagged()) {
    367372                    continue;
    368373                }
    369                 Collection<OsmPrimitive> referringPrimitives = n.getReferrers();
     374                Collection<IPrimitive> referringPrimitives = new HashSet<>(n.getReferrers());
    370375                referringPrimitives.removeAll(primitivesToDelete);
    371376                int count = 0;
    372                 for (OsmPrimitive p : referringPrimitives) {
     377                for (IPrimitive p : referringPrimitives) {
    373378                    if (!p.isDeleted()) {
    374379                        count++;
    375380                    }
     
    396401     * @return command a command to perform the deletions, or null if there is nothing to delete.
    397402     * @since 12718
    398403     */
    399     public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
     404    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> delete(Collection<? extends O> selection, boolean alsoDeleteNodesInWay) {
    400405        return delete(selection, alsoDeleteNodesInWay, false /* not silent */);
    401406    }
    402407
     
    415420     * @return command a command to perform the deletions, or null if there is nothing to delete.
    416421     * @since 12718
    417422     */
    418     public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay, boolean silent) {
     423    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> delete(Collection<? extends O> selection, boolean alsoDeleteNodesInWay, boolean silent) {
    419424        if (selection == null || selection.isEmpty())
    420425            return null;
    421426
    422         Set<OsmPrimitive> primitivesToDelete = new HashSet<>(selection);
     427        Set<IPrimitive> primitivesToDelete = new HashSet<>(selection);
    423428
    424         Collection<Relation> relationsToDelete = Utils.filteredCollection(primitivesToDelete, Relation.class);
     429        Collection<R> relationsToDelete = Utils.filteredCollection(primitivesToDelete, R);
    425430        if (!relationsToDelete.isEmpty() && !silent && !callback.confirmRelationDeletion(relationsToDelete))
    426431            return null;
    427432
    428433        if (alsoDeleteNodesInWay) {
    429434            // delete untagged nodes only referenced by primitives in primitivesToDelete, too
    430             Collection<Node> nodesToDelete = computeNodesToDelete(primitivesToDelete);
     435            Collection<INode> nodesToDelete = computeNodesToDelete(primitivesToDelete);
    431436            primitivesToDelete.addAll(nodesToDelete);
    432437        }
    433438
    434439        if (!silent && !callback.checkAndConfirmOutlyingDelete(
    435                 primitivesToDelete, Utils.filteredCollection(primitivesToDelete, Way.class)))
     440                primitivesToDelete, Utils.filteredCollection(primitivesToDelete, IWay.class)))
    436441            return null;
    437442
    438         Collection<Way> waysToBeChanged = primitivesToDelete.stream()
    439                 .flatMap(p -> p.referrers(Way.class))
     443        Collection<IWay<?>> waysToBeChanged = primitivesToDelete.stream()
     444                .flatMap(p -> p.getReferrers().stream().filter(IWay.class::isInstance).map(IWay.class::cast))
    440445                .collect(Collectors.toSet());
    441446
    442447        Collection<Command> cmds = new LinkedList<>();
    443         Set<Node> nodesToRemove = new HashSet<>(Utils.filteredCollection(primitivesToDelete, Node.class));
    444         for (Way w : waysToBeChanged) {
    445             Way wnew = new Way(w);
     448        Set<INode> nodesToRemove = new HashSet<>(Utils.filteredCollection(primitivesToDelete, INode.class));
     449        for (IWay<?> w : waysToBeChanged) {
     450            IWay<?> wnew = Utils.clone(w);
    446451            wnew.removeNodes(nodesToRemove);
    447452            if (wnew.getNodesCount() < 2) {
    448453                primitivesToDelete.add(w);
     
    463468
    464469        // remove the objects from their parent relations
    465470        //
    466         final Set<Relation> relationsToBeChanged = primitivesToDelete.stream()
    467                 .flatMap(p -> p.referrers(Relation.class))
     471        final Set<IRelation<?>> relationsToBeChanged = primitivesToDelete.stream()
     472                .flatMap(p -> p.getReferrers().stream().filter(IRelation.class::isInstance).map(IRelation.class::cast))
    468473                .collect(Collectors.toSet());
    469         for (Relation cur : relationsToBeChanged) {
    470             Relation rel = new Relation(cur);
     474        for (IRelation<?> cur : relationsToBeChanged) {
     475            IRelation<?> rel = Utils.clone(cur);
    471476            rel.removeMembersFor(primitivesToDelete);
    472477            cmds.add(new ChangeCommand(cur, rel));
    473478        }
     
    475480        // build the delete command
    476481        //
    477482        if (!primitivesToDelete.isEmpty()) {
    478             cmds.add(new DeleteCommand(primitivesToDelete.iterator().next().getDataSet(), primitivesToDelete));
     483            cmds.add(new DeleteCommand<>(primitivesToDelete.iterator().next().getDataSet(), primitivesToDelete));
    479484        }
    480485
    481         return new SequenceCommand(tr("Delete"), cmds);
     486        return SequenceCommand.createSimplifiedSequenceCommand(tr("Delete"), cmds);
    482487    }
    483488
    484489    /**
     
    487492     * @return A matching command to safely delete that segment.
    488493     * @since 12718
    489494     */
    490     public static Command deleteWaySegment(WaySegment ws) {
     495    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> deleteWaySegment(WaySegment<N, W> ws) {
    491496        if (ws.way.getNodesCount() < 3)
    492497            return delete(Collections.singleton(ws.way), false);
    493498
     
    494499        if (ws.way.isClosed()) {
    495500            // If the way is circular (first and last nodes are the same), the way shouldn't be splitted
    496501
    497             List<Node> n = new ArrayList<>();
     502            List<N> n = new ArrayList<>();
    498503
    499504            n.addAll(ws.way.getNodes().subList(ws.lowerIndex + 1, ws.way.getNodesCount() - 1));
    500505            n.addAll(ws.way.getNodes().subList(0, ws.lowerIndex + 1));
    501506
    502             Way wnew = new Way(ws.way);
     507            W wnew = Utils.clone(ws.way);
    503508            wnew.setNodes(n);
    504509
    505510            return new ChangeCommand(ws.way, wnew);
    506511        }
    507512
    508         List<Node> n1 = new ArrayList<>();
    509         List<Node> n2 = new ArrayList<>();
     513        List<N> n1 = new ArrayList<>();
     514        List<N> n2 = new ArrayList<>();
    510515
    511516        n1.addAll(ws.way.getNodes().subList(0, ws.lowerIndex + 1));
    512517        n2.addAll(ws.way.getNodes().subList(ws.lowerIndex + 1, ws.way.getNodesCount()));
    513518
    514         Way wnew = new Way(ws.way);
     519        W wnew = Utils.clone(ws.way);
    515520
    516521        if (n1.size() < 2) {
    517522            wnew.setNodes(n2);
  • src/org/openstreetmap/josm/command/MoveCommand.java

     
    1010import java.util.List;
    1111import java.util.NoSuchElementException;
    1212import java.util.Objects;
     13import java.util.stream.Collectors;
    1314
    1415import javax.swing.Icon;
    1516
    1617import org.openstreetmap.josm.data.coor.EastNorth;
    1718import org.openstreetmap.josm.data.coor.LatLon;
    18 import org.openstreetmap.josm.data.osm.DataSet;
    19 import org.openstreetmap.josm.data.osm.Node;
    20 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     19import org.openstreetmap.josm.data.osm.INode;
     20import org.openstreetmap.josm.data.osm.IPrimitive;
     21import org.openstreetmap.josm.data.osm.IRelation;
     22import org.openstreetmap.josm.data.osm.IWay;
     23import org.openstreetmap.josm.data.osm.OsmData;
    2124import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
    2225import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    2326import org.openstreetmap.josm.tools.ImageProvider;
     
    2730 * to collect several MoveCommands into one command.
    2831 *
    2932 * @author imi
     33 * @param <O> the base type of primitives
     34 * @param <N> type representing nodes
     35 * @param <W> type representing ways
     36 * @param <R> type representing relations
    3037 */
    31 public class MoveCommand extends Command {
     38public class MoveCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
    3239    /**
    3340     * The objects that should be moved.
    3441     */
    35     private Collection<Node> nodes = new LinkedList<>();
     42    private Collection<N> nodes = new LinkedList<>();
    3643    /**
    3744     * Starting position, base command point, current (mouse-drag) position = startEN + (x,y) =
    3845     */
     
    6168     * @param x X difference movement. Coordinates are in northern/eastern
    6269     * @param y Y difference movement. Coordinates are in northern/eastern
    6370     */
    64     public MoveCommand(OsmPrimitive osm, double x, double y) {
     71    public MoveCommand(O osm, double x, double y) {
    6572        this(Collections.singleton(osm), x, y);
    6673    }
    6774
     
    7077     * @param node The node to move
    7178     * @param position The new location (lat/lon)
    7279     */
    73     public MoveCommand(Node node, LatLon position) {
    74         this(Collections.singleton((OsmPrimitive) node),
     80    public MoveCommand(N node, LatLon position) {
     81        this(Collections.singleton((O) node),
    7582                ProjectionRegistry.getProjection().latlon2eastNorth(position).subtract(node.getEastNorth()));
    7683    }
    7784
     
    8087     * @param objects The primitives to move
    8188     * @param offset The movement vector
    8289     */
    83     public MoveCommand(Collection<OsmPrimitive> objects, EastNorth offset) {
     90    public MoveCommand(Collection<O> objects, EastNorth offset) {
    8491        this(objects, offset.getX(), offset.getY());
    8592    }
    8693
     
    9299     * @throws NullPointerException if objects is null or contain null item
    93100     * @throws NoSuchElementException if objects is empty
    94101     */
    95     public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
     102    public MoveCommand(Collection<O> objects, double x, double y) {
    96103        this(objects.iterator().next().getDataSet(), objects, x, y);
    97104    }
    98105
     
    106113     * @throws NoSuchElementException if objects is empty
    107114     * @since 12759
    108115     */
    109     public MoveCommand(DataSet ds, Collection<OsmPrimitive> objects, double x, double y) {
     116    public MoveCommand(OsmData<O, N, W, R> ds, Collection<O> objects, double x, double y) {
    110117        super(ds);
    111118        startEN = null;
    112119        saveCheckpoint(); // (0,0) displacement will be saved
     
    114121        this.y = y;
    115122        Objects.requireNonNull(objects, "objects");
    116123        this.nodes = AllNodesVisitor.getAllNodes(objects);
    117         for (Node n : this.nodes) {
     124        for (INode n : this.nodes) {
    118125            oldState.add(new OldNodeState(n));
    119126        }
    120127    }
     
    127134     * @param end The ending position (northern/eastern)
    128135     * @since 12759
    129136     */
    130     public MoveCommand(DataSet ds, Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
     137    public MoveCommand(OsmData<O, N, W, R> ds, Collection<O> objects, EastNorth start, EastNorth end) {
    131138        this(Objects.requireNonNull(ds, "ds"),
    132139             Objects.requireNonNull(objects, "objects"),
    133140             Objects.requireNonNull(end, "end").getX() - Objects.requireNonNull(start, "start").getX(),
     
    141148     * @param start The starting position (northern/eastern)
    142149     * @param end The ending position (northern/eastern)
    143150     */
    144     public MoveCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
     151    public MoveCommand(Collection<O> objects, EastNorth start, EastNorth end) {
    145152        this(Objects.requireNonNull(objects, "objects").iterator().next().getDataSet(), objects, start, end);
    146153    }
    147154
     
    153160     * @param end The ending position (northern/eastern)
    154161     * @since 12759
    155162     */
    156     public MoveCommand(DataSet ds, OsmPrimitive p, EastNorth start, EastNorth end) {
     163    public MoveCommand(OsmData<O, N, W, R> ds, O p, EastNorth start, EastNorth end) {
    157164        this(ds, Collections.singleton(Objects.requireNonNull(p, "p")), start, end);
    158165    }
    159166
     
    163170     * @param start The starting position (northern/eastern)
    164171     * @param end The ending position (northern/eastern)
    165172     */
    166     public MoveCommand(OsmPrimitive p, EastNorth start, EastNorth end) {
     173    public MoveCommand(O p, EastNorth start, EastNorth end) {
    167174        this(Collections.singleton(Objects.requireNonNull(p, "p")), start, end);
    168175    }
    169176
     
    179186     * @param y Y difference movement. Coordinates are in northern/eastern
    180187     */
    181188    public void moveAgain(double x, double y) {
    182         for (Node n : nodes) {
     189        for (INode n : nodes) {
    183190            EastNorth eastNorth = n.getEastNorth();
    184191            if (eastNorth != null) {
    185192                n.setEastNorth(eastNorth.add(x, y));
     
    239246
    240247    private void updateCoordinates() {
    241248        Iterator<OldNodeState> it = oldState.iterator();
    242         for (Node n : nodes) {
     249        for (INode n : nodes) {
    243250            OldNodeState os = it.next();
    244251            if (os.getEastNorth() != null) {
    245252                n.setEastNorth(os.getEastNorth().add(x, y));
     
    251258    public boolean executeCommand() {
    252259        ensurePrimitivesAreInDataset();
    253260
    254         for (Node n : nodes) {
     261        for (INode n : nodes) {
    255262            // in case #3892 happens again
    256263            if (n == null)
    257264                throw new AssertionError("null detected in node list");
     
    269276        ensurePrimitivesAreInDataset();
    270277
    271278        Iterator<OldNodeState> it = oldState.iterator();
    272         for (Node n : nodes) {
     279        for (INode n : nodes) {
    273280            OldNodeState os = it.next();
    274281            n.setCoor(os.getLatLon());
    275282            n.setModified(os.isModified());
     
    277284    }
    278285
    279286    @Override
    280     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    281         for (OsmPrimitive osm : nodes) {
    282             modified.add(osm);
     287    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
     288        for (N osm : nodes) {
     289            modified.add((O) osm);
    283290        }
    284291    }
    285292
     
    294301    }
    295302
    296303    @Override
    297     public Collection<Node> getParticipatingPrimitives() {
    298         return nodes;
     304    public Collection<? extends O> getParticipatingPrimitives() {
     305        return nodes.stream().map(n -> (O) n).collect(Collectors.toList());
    299306    }
    300307
    301308    /**
  • src/org/openstreetmap/josm/command/PseudoCommand.java

     
    55
    66import javax.swing.Icon;
    77
    8 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     8import org.openstreetmap.josm.data.osm.IPrimitive;
    99
    1010/**
    1111 * PseudoCommand is a reduced form of a command. It can be presented in a tree view
     
    3434     * Return the primitives that take part in this command.
    3535     * @return primitives that take part in this command
    3636     */
    37     Collection<? extends OsmPrimitive> getParticipatingPrimitives();
     37    Collection<? extends IPrimitive> getParticipatingPrimitives();
    3838
    3939    /**
    4040     * Returns the subcommands of this command.
  • src/org/openstreetmap/josm/command/PurgeCommand.java

     
    55
    66import java.util.ArrayList;
    77import java.util.Collection;
     8import java.util.Collections;
    89import java.util.HashMap;
    910import java.util.HashSet;
    1011import java.util.Iterator;
     
    1718
    1819import org.openstreetmap.josm.data.conflict.Conflict;
    1920import org.openstreetmap.josm.data.conflict.ConflictCollection;
    20 import org.openstreetmap.josm.data.osm.DataSet;
     21import org.openstreetmap.josm.data.osm.INode;
     22import org.openstreetmap.josm.data.osm.IPrimitive;
     23import org.openstreetmap.josm.data.osm.IRelation;
     24import org.openstreetmap.josm.data.osm.IWay;
    2125import org.openstreetmap.josm.data.osm.Node;
    2226import org.openstreetmap.josm.data.osm.NodeData;
     27import org.openstreetmap.josm.data.osm.OsmData;
    2328import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2429import org.openstreetmap.josm.data.osm.PrimitiveData;
    2530import org.openstreetmap.josm.data.osm.PrimitiveId;
     
    3439
    3540/**
    3641 * Command, to purge a list of primitives.
     42 * @param <O> the base type of primitives
     43 * @param <N> type representing nodes
     44 * @param <W> type representing ways
     45 * @param <R> type representing relations
    3746 */
    38 public class PurgeCommand extends Command {
    39     protected List<OsmPrimitive> toPurge;
     47public class PurgeCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
     48    protected List<O> toPurge;
    4049    protected Storage<PrimitiveData> makeIncompleteData;
    4150
    4251    protected Map<PrimitiveId, PrimitiveData> makeIncompleteDataByPrimId;
     
    5463     * @param makeIncomplete primitives to make incomplete
    5564     * @since 11240
    5665     */
    57     public PurgeCommand(DataSet data, Collection<OsmPrimitive> toPurge, Collection<OsmPrimitive> makeIncomplete) {
     66    public PurgeCommand(OsmData<O, N, W, R> data, Collection<O> toPurge, Collection<O> makeIncomplete) {
    5867        super(data);
    5968        init(toPurge, makeIncomplete);
    6069    }
    6170
    62     private void init(Collection<OsmPrimitive> toPurge, Collection<OsmPrimitive> makeIncomplete) {
     71    private void init(Collection<O> toPurge, Collection<O> makeIncomplete) {
    6372        /**
    6473         * The topological sort is to avoid missing way nodes and missing
    6574         * relation members when adding primitives back to the dataset on undo.
     
    7281        saveIncomplete(makeIncomplete);
    7382    }
    7483
    75     protected final void saveIncomplete(Collection<OsmPrimitive> makeIncomplete) {
     84    protected final void saveIncomplete(Collection<O> makeIncomplete) {
    7685        makeIncompleteData = new Storage<>(new Storage.PrimitiveIdHash());
    7786        makeIncompleteDataByPrimId = makeIncompleteData.foreignKey(new Storage.PrimitiveIdHash());
    7887
    79         for (OsmPrimitive osm : makeIncomplete) {
     88        for (O osm : makeIncomplete) {
    8089            makeIncompleteData.add(osm.save());
    8190        }
    8291    }
     
    8998            getAffectedDataSet().clearSelection(toPurge);
    9099            // Loop from back to front to keep referential integrity.
    91100            for (int i = toPurge.size()-1; i >= 0; --i) {
    92                 OsmPrimitive osm = toPurge.get(i);
     101                O osm = toPurge.get(i);
    93102                if (makeIncompleteDataByPrimId.containsKey(osm)) {
    94103                    // we could simply set the incomplete flag
    95104                    // but that would not free memory in case the
     
    124133            return;
    125134
    126135        getAffectedDataSet().update(() -> {
    127             for (OsmPrimitive osm : toPurge) {
     136            for (O osm : toPurge) {
    128137                PrimitiveData data = makeIncompleteDataByPrimId.get(osm);
    129138                if (data != null) {
    130139                    if (getAffectedDataSet().getPrimitiveById(osm) != osm)
     
    151160     * @param sel collection of primitives to sort
    152161     * @return sorted list
    153162     */
    154     public static List<OsmPrimitive> topoSort(Collection<OsmPrimitive> sel) {
    155         Set<OsmPrimitive> in = new HashSet<>(sel);
    156         List<OsmPrimitive> out = new ArrayList<>(in.size());
    157         Set<Relation> inR = new HashSet<>();
     163    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> List<O> topoSort(Collection<O> sel) {
     164        if (sel == null || sel.isEmpty()) return Collections.emptyList();
     165        OsmData<O, N, W, R> data = sel.iterator().next().getDataSet();
     166        Set<O> in = new HashSet<>(sel);
     167        List<O> out = new ArrayList<>(in.size());
     168        Set<R> inR = new HashSet<>();
    158169
    159170        // Nodes not deleted in the first pass
    160         Set<OsmPrimitive> remainingNodes = new HashSet<>(in.size());
     171        Set<O> remainingNodes = new HashSet<>(in.size());
    161172
    162173        /**
    163174         *  First add nodes that have no way referrer.
    164175         */
    165176        outer:
    166             for (Iterator<OsmPrimitive> it = in.iterator(); it.hasNext();) {
    167                 OsmPrimitive u = it.next();
    168                 if (u instanceof Node) {
    169                     Node n = (Node) u;
    170                     for (OsmPrimitive ref : n.getReferrers()) {
    171                         if (ref instanceof Way && in.contains(ref)) {
     177            for (Iterator<O> it = in.iterator(); it.hasNext();) {
     178                O u = it.next();
     179                if (u instanceof INode) {
     180                    N n = (N) u;
     181                    for (IPrimitive ref : n.getReferrers()) {
     182                        if (ref instanceof IWay && in.contains(ref)) {
    172183                            it.remove();
    173                             remainingNodes.add(n);
     184                            remainingNodes.add((O) n);
    174185                            continue outer;
    175186                        }
    176187                    }
    177188                    it.remove();
    178                     out.add(n);
     189                    out.add((O) n);
    179190                }
    180191            }
    181192
     
    182193        /**
    183194         * Then add all ways, each preceded by its (remaining) nodes.
    184195         */
    185         for (Iterator<OsmPrimitive> it = in.iterator(); it.hasNext();) {
    186             OsmPrimitive u = it.next();
    187             if (u instanceof Way) {
    188                 Way w = (Way) u;
     196        for (Iterator<O> it = in.iterator(); it.hasNext();) {
     197            O u = it.next();
     198            if (u instanceof IWay) {
     199                W w = (W) u;
    189200                it.remove();
    190                 for (Node n : w.getNodes()) {
     201                for (N n : w.getNodes()) {
    191202                    if (remainingNodes.contains(n)) {
    192203                        remainingNodes.remove(n);
    193                         out.add(n);
     204                        out.add((O) n);
    194205                    }
    195206                }
    196                 out.add(w);
     207                out.add((O) w);
    197208            } else if (u instanceof Relation) {
    198                 inR.add((Relation) u);
     209                inR.add((R) u);
    199210            }
    200211        }
    201212
     
    205216        // Do topological sorting on a DAG where each arrow points from child to parent.
    206217        //  (Because it is faster to loop over getReferrers() than getMembers().)
    207218
    208         Map<Relation, Integer> numChilds = new HashMap<>();
     219        Map<R, Integer> numChilds = new HashMap<>();
    209220
    210221        // calculate initial number of childs
    211         for (Relation r : inR) {
     222        for (R r : inR) {
    212223            numChilds.put(r, 0);
    213224        }
    214         for (Relation r : inR) {
    215             for (OsmPrimitive parent : r.getReferrers()) {
    216                 if (!(parent instanceof Relation))
     225        for (R r : inR) {
     226            for (IPrimitive parent : r.getReferrers()) {
     227                if (!(parent instanceof IRelation))
    217228                    throw new AssertionError();
    218229                Integer i = numChilds.get(parent);
    219230                if (i != null) {
    220                     numChilds.put((Relation) parent, i+1);
     231                    numChilds.put((R) parent, i+1);
    221232                }
    222233            }
    223234        }
    224         Set<Relation> childlessR = new HashSet<>();
    225         for (Relation r : inR) {
     235        Set<R> childlessR = new HashSet<>();
     236        for (R r : inR) {
    226237            if (numChilds.get(r).equals(0)) {
    227238                childlessR.add(r);
    228239            }
    229240        }
    230241
    231         List<Relation> outR = new ArrayList<>(inR.size());
     242        List<R> outR = new ArrayList<>(inR.size());
    232243        while (!childlessR.isEmpty()) {
    233244            // Identify one childless Relation and let it virtually die. This makes other relations childless.
    234             Iterator<Relation> it = childlessR.iterator();
    235             Relation next = it.next();
     245            Iterator<R> it = childlessR.iterator();
     246            R next = it.next();
    236247            it.remove();
    237248            outR.add(next);
    238249
    239             for (OsmPrimitive parentPrim : next.getReferrers()) {
    240                 Relation parent = (Relation) parentPrim;
     250            for (IPrimitive parentPrim : next.getReferrers()) {
     251                R parent = (R) parentPrim;
    241252                Integer i = numChilds.get(parent);
    242253                if (i != null) {
    243254                    numChilds.put(parent, i-1);
     
    251262        if (outR.size() != inR.size())
    252263            throw new AssertionError("topo sort algorithm failed");
    253264
    254         out.addAll(outR);
     265        outR.forEach(r -> out.add((O) r));
    255266
    256267        return out;
    257268    }
     
    267278    }
    268279
    269280    @Override
    270     public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
     281    public Collection<O> getParticipatingPrimitives() {
    271282        return toPurge;
    272283    }
    273284
    274285    @Override
    275     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     286    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
    276287        // Do nothing
    277288    }
    278289
     
    286297        if (this == obj) return true;
    287298        if (obj == null || getClass() != obj.getClass()) return false;
    288299        if (!super.equals(obj)) return false;
    289         PurgeCommand that = (PurgeCommand) obj;
     300        PurgeCommand<?, ?, ?, ?> that = (PurgeCommand<?, ?, ?, ?>) obj;
    290301        return Objects.equals(toPurge, that.toPurge) &&
    291302                Objects.equals(makeIncompleteData, that.makeIncompleteData) &&
    292303                Objects.equals(makeIncompleteDataByPrimId, that.makeIncompleteDataByPrimId) &&
  • src/org/openstreetmap/josm/command/RemoveNodesCommand.java

     
    88import org.openstreetmap.josm.data.osm.DataSet;
    99import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    1010import org.openstreetmap.josm.data.osm.Node;
     11import org.openstreetmap.josm.data.osm.OsmPrimitive;
     12import org.openstreetmap.josm.data.osm.Relation;
    1113import org.openstreetmap.josm.data.osm.Way;
    1214
    1315/**
     
    1719 *
    1820 * @author Giuseppe Bilotta
    1921 */
    20 public class RemoveNodesCommand extends AbstractNodesCommand<Set<Node>> {
     22public class RemoveNodesCommand extends AbstractNodesCommand<OsmPrimitive, Node, Way, Relation, Set<Node>> {
    2123
    2224    /**
    2325     * Constructs a new {@code RemoveNodesCommand}.
  • src/org/openstreetmap/josm/command/RotateCommand.java

     
    77import java.util.Objects;
    88
    99import org.openstreetmap.josm.data.coor.EastNorth;
    10 import org.openstreetmap.josm.data.osm.Node;
     10import org.openstreetmap.josm.data.osm.INode;
    1111import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1212
    1313/**
     
    8484    protected void transformNodes() {
    8585        double cosPhi = Math.cos(rotationAngle);
    8686        double sinPhi = Math.sin(rotationAngle);
    87         for (Node n : nodes) {
     87        for (INode n : nodes) {
    8888            EastNorth oldEastNorth = oldStates.get(n).getEastNorth();
    8989            double x = oldEastNorth.east() - pivot.east();
    9090            double y = oldEastNorth.north() - pivot.north();
  • src/org/openstreetmap/josm/command/SelectCommand.java

     
    99import java.util.Objects;
    1010
    1111import org.openstreetmap.josm.data.osm.DataSet;
     12import org.openstreetmap.josm.data.osm.Node;
    1213import org.openstreetmap.josm.data.osm.OsmPrimitive;
     14import org.openstreetmap.josm.data.osm.Relation;
     15import org.openstreetmap.josm.data.osm.Way;
    1316
    1417/**
    1518 * Command that selects OSM primitives
     
    1619 *
    1720 * @author Landwirt
    1821 */
    19 public class SelectCommand extends Command {
     22public class SelectCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    2023
    2124    /** the primitives to select when executing the command */
    2225    private final Collection<OsmPrimitive> newSelection;
  • src/org/openstreetmap/josm/command/SequenceCommand.java

     
    1010
    1111import javax.swing.Icon;
    1212
    13 import org.openstreetmap.josm.data.osm.DataSet;
    14 import org.openstreetmap.josm.data.osm.OsmPrimitive;
     13import org.openstreetmap.josm.data.osm.INode;
     14import org.openstreetmap.josm.data.osm.IPrimitive;
     15import org.openstreetmap.josm.data.osm.IRelation;
     16import org.openstreetmap.josm.data.osm.IWay;
     17import org.openstreetmap.josm.data.osm.OsmData;
    1518import org.openstreetmap.josm.tools.ImageProvider;
    1619import org.openstreetmap.josm.tools.Utils;
    1720
     
    1922 * A command consisting of a sequence of other commands. Executes the other commands
    2023 * and undo them in reverse order.
    2124 * @author imi
     25 * @param <O> the base type of primitives
     26 * @param <N> type representing nodes
     27 * @param <W> type representing ways
     28 * @param <R> type representing relations
    2229 * @since 31
    2330 */
    24 public class SequenceCommand extends Command {
     31public class SequenceCommand<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends Command<O, N, W, R> {
    2532
    2633    /** The command sequence to be executed. */
    27     private Command[] sequence;
     34    private Command<O, N, W, R>[] sequence;
    2835    private boolean sequenceComplete;
    2936    private final String name;
    3037    /** Determines if the sequence execution should continue after one of its commands fails. */
     
    3845     * @param continueOnError Determines if the sequence execution should continue after one of its commands fails
    3946     * @since 12726
    4047     */
    41     public SequenceCommand(DataSet ds, String name, Collection<Command> sequenz, boolean continueOnError) {
     48    public SequenceCommand(OsmData<O, N, W, R> ds, String name, Collection<Command<O, N, W, R>> sequenz, boolean continueOnError) {
    4249        super(ds);
    4350        this.name = name;
    4451        this.sequence = sequenz.toArray(new Command[0]);
     
    5259     * @param continueOnError Determines if the sequence execution should continue after one of its commands fails
    5360     * @since 11874
    5461     */
    55     public SequenceCommand(String name, Collection<Command> sequenz, boolean continueOnError) {
     62    public SequenceCommand(String name, Collection<Command<O, N, W, R>> sequenz, boolean continueOnError) {
    5663        this(sequenz.iterator().next().getAffectedDataSet(), name, sequenz, continueOnError);
    5764    }
    5865
     
    6168     * @param name The description text
    6269     * @param sequenz The sequence that should be executed.
    6370     */
    64     public SequenceCommand(String name, Collection<Command> sequenz) {
     71    public SequenceCommand(String name, Collection<Command<O, N, W, R>> sequenz) {
    6572        this(name, sequenz, false);
    6673    }
    6774
     
    7077     * @param name The description text
    7178     * @param sequenz The sequence that should be executed.
    7279     */
    73     public SequenceCommand(String name, Command... sequenz) {
     80    public SequenceCommand(String name, Command<O, N, W, R>... sequenz) {
    7481        this(name, Arrays.asList(sequenz));
    7582    }
    7683
     84    /**
     85     * Convenient constructor, if the commands are known at compile time.
     86     * @param name The description text to be used for the sequence command, if one is created.
     87     * @param sequenz The sequence that should be executed.
     88     * @param <O> the base type of primitives
     89     * @param <N> type representing nodes
     90     * @param <W> type representing ways
     91     * @param <R> type representing relations
     92     * @return Either a SequenceCommand, or the only command in the potential sequence
     93     * @since xxx
     94     */
     95    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> createSimplifiedSequenceCommand(String name, Command<O, N, W, R>... sequenz) {
     96        if (sequenz.length == 1) {
     97            return sequenz[0];
     98        }
     99        return new SequenceCommand<>(name, sequenz);
     100    }
     101
     102    /**
     103     * Convenient constructor, if the commands are known at compile time.
     104     * @param name The description text to be used for the sequence command, if one is created.
     105     * @param sequenz The sequence that should be executed.
     106     * @param <O> the base type of primitives
     107     * @param <N> type representing nodes
     108     * @param <W> type representing ways
     109     * @param <R> type representing relations
     110     * @return Either a SequenceCommand, or the only command in the potential sequence
     111     * @since xxx
     112     */
     113    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Command<O, N, W, R> createSimplifiedSequenceCommand(String name, Collection<Command<O, N, W, R>> sequenz) {
     114        if (sequenz.size() == 1) {
     115            return sequenz.iterator().next();
     116        }
     117        return new SequenceCommand<>(name, sequenz);
     118    }
     119
    77120    @Override public boolean executeCommand() {
    78121        for (int i = 0; i < sequence.length; i++) {
    79122            boolean result = sequence[i].executeCommand();
     
    90133     * Returns the last command.
    91134     * @return The last command, or {@code null} if the sequence is empty.
    92135     */
    93     public Command getLastCommand() {
     136    public Command<O, N, W, R> getLastCommand() {
    94137        if (sequence.length == 0)
    95138            return null;
    96139        return sequence[sequence.length-1];
     
    112155    }
    113156
    114157    @Override
    115     public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    116         for (Command c : sequence) {
     158    public void fillModifiedData(Collection<O> modified, Collection<O> deleted, Collection<O> added) {
     159        for (Command<O, N, W, R> c : sequence) {
    117160            c.fillModifiedData(modified, deleted, added);
    118161        }
    119162    }
     
    143186    }
    144187
    145188    @Override
    146     public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
    147         Collection<OsmPrimitive> prims = new HashSet<>();
    148         for (Command c : sequence) {
     189    public Collection<O> getParticipatingPrimitives() {
     190        Collection<O> prims = new HashSet<>();
     191        for (Command<O, N, W, R> c : sequence) {
    149192            prims.addAll(c.getParticipatingPrimitives());
    150193        }
    151194        return prims;
    152195    }
    153196
    154     protected final void setSequence(Command... sequence) {
     197    protected final void setSequence(Command<O, N, W, R>... sequence) {
    155198        this.sequence = Utils.copyArray(sequence);
    156199    }
    157200
     
    169212        if (this == obj) return true;
    170213        if (obj == null || getClass() != obj.getClass()) return false;
    171214        if (!super.equals(obj)) return false;
    172         SequenceCommand that = (SequenceCommand) obj;
     215        SequenceCommand<?, ?, ?, ?> that = (SequenceCommand<?, ?, ?, ?>) obj;
    173216        return sequenceComplete == that.sequenceComplete &&
    174217                continueOnError == that.continueOnError &&
    175218                Arrays.equals(sequence, that.sequence) &&
  • src/org/openstreetmap/josm/command/TransformNodesCommand.java

     
    88import java.util.Map;
    99import java.util.NoSuchElementException;
    1010import java.util.Objects;
     11import java.util.stream.Collectors;
    1112
    1213import javax.swing.Icon;
    1314
    1415import org.openstreetmap.josm.data.coor.EastNorth;
     16import org.openstreetmap.josm.data.osm.INode;
    1517import org.openstreetmap.josm.data.osm.Node;
    1618import org.openstreetmap.josm.data.osm.OsmPrimitive;
     19import org.openstreetmap.josm.data.osm.Relation;
     20import org.openstreetmap.josm.data.osm.Way;
    1721import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
    1822import org.openstreetmap.josm.tools.ImageProvider;
    1923
     
    2226 *
    2327 * @author Olivier Croquette &lt;ocroquette@free.fr&gt;
    2428 */
    25 public abstract class TransformNodesCommand extends Command {
     29public abstract class TransformNodesCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    2630
    2731    /**
    2832     * The nodes to transform.
    2933     */
    30     protected final Collection<Node> nodes;
     34    protected final Collection<INode> nodes;
    3135
    3236    /**
    3337     * List of all old states of the nodes.
    3438     */
    35     protected final Map<Node, OldNodeState> oldStates = new HashMap<>();
     39    protected final Map<INode, OldNodeState> oldStates = new HashMap<>();
    3640
    3741    /**
    3842     * Stores the state of the nodes before the command.
    3943     */
    4044    protected final void storeOldState() {
    41         for (Node n : this.nodes) {
     45        for (INode n : this.nodes) {
    4246            oldStates.put(n, new OldNodeState(n));
    4347        }
    4448    }
     
    8589     * Flag all nodes as modified.
    8690     */
    8791    public void flagNodesAsModified() {
    88         for (Node n : nodes) {
     92        for (INode n : nodes) {
    8993            n.setModified(true);
    9094        }
    9195    }
     
    9599     */
    96100    @Override
    97101    public void undoCommand() {
    98         for (Node n : nodes) {
     102        for (INode n : nodes) {
    99103            OldNodeState os = oldStates.get(n);
    100104            n.setCoor(os.getLatLon());
    101105            n.setModified(os.isModified());
     
    108112
    109113    @Override
    110114    public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
    111         return nodes;
     115        return getTransformedNodes();
    112116    }
    113117
    114118    @Override
     
    126130     * @return nodes with the current transformation applied
    127131     */
    128132    public Collection<Node> getTransformedNodes() {
    129         return nodes;
     133        return nodes.stream().filter(Node.class::isInstance).map(Node.class::cast).collect(Collectors.toList());
    130134    }
    131135
    132136    /**
     
    138142    public EastNorth getNodesCenter() {
    139143        EastNorth sum = new EastNorth(0, 0);
    140144
    141         for (Node n : nodes) {
     145        for (INode n : nodes) {
    142146            EastNorth en = n.getEastNorth();
    143147            sum = sum.add(en.east(), en.north());
    144148        }
  • src/org/openstreetmap/josm/command/conflict/ConflictAddCommand.java

     
    1313import org.openstreetmap.josm.data.conflict.Conflict;
    1414import org.openstreetmap.josm.data.osm.DataSet;
    1515import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     16import org.openstreetmap.josm.data.osm.Node;
    1617import org.openstreetmap.josm.data.osm.OsmDataManager;
    1718import org.openstreetmap.josm.data.osm.OsmPrimitive;
     19import org.openstreetmap.josm.data.osm.Relation;
     20import org.openstreetmap.josm.data.osm.Way;
    1821import org.openstreetmap.josm.gui.MainApplication;
    1922import org.openstreetmap.josm.tools.ImageProvider;
    2023import org.openstreetmap.josm.tools.Logging;
     
    2427 * Command used to add a new conflict.
    2528 * @since 1857
    2629 */
    27 public class ConflictAddCommand extends Command {
     30public class ConflictAddCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    2831    private final Conflict<? extends OsmPrimitive> conflict;
    2932
    3033    /**
     
    5558    @Override
    5659    public boolean executeCommand() {
    5760        try {
    58             getAffectedDataSet().getConflicts().add(conflict);
     61            ((DataSet) getAffectedDataSet()).getConflicts().add(conflict);
    5962        } catch (IllegalStateException e) {
    6063            Logging.error(e);
    6164            warnBecauseOfDoubleConflict();
     
    6568
    6669    @Override
    6770    public void undoCommand() {
    68         DataSet ds = getAffectedDataSet();
     71        DataSet ds = (DataSet) getAffectedDataSet();
    6972        if (!OsmDataManager.getInstance().containsDataSet(ds)) {
    7073            Logging.warn(tr("Layer ''{0}'' does not exist any more. Cannot remove conflict for object ''{1}''.",
    7174                    ds.getName(),
  • src/org/openstreetmap/josm/command/conflict/ConflictResolveCommand.java

     
    99import org.openstreetmap.josm.data.conflict.Conflict;
    1010import org.openstreetmap.josm.data.conflict.ConflictCollection;
    1111import org.openstreetmap.josm.data.osm.DataSet;
     12import org.openstreetmap.josm.data.osm.Node;
    1213import org.openstreetmap.josm.data.osm.OsmDataManager;
     14import org.openstreetmap.josm.data.osm.OsmPrimitive;
     15import org.openstreetmap.josm.data.osm.Relation;
     16import org.openstreetmap.josm.data.osm.Way;
    1317import org.openstreetmap.josm.tools.Logging;
    1418
    1519/**
     
    2024 * it reconstitutes them.
    2125 *
    2226 */
    23 public abstract class ConflictResolveCommand extends Command {
     27public abstract class ConflictResolveCommand extends Command<OsmPrimitive, Node, Way, Relation> {
    2428    /** the list of resolved conflicts */
    2529    private final ConflictCollection resolvedConflicts = new ConflictCollection();
    2630
     
    4953     *
    5054     */
    5155    protected void reconstituteConflicts() {
    52         DataSet ds = getAffectedDataSet();
     56        DataSet ds = (DataSet) getAffectedDataSet();
    5357        for (Conflict<?> c : resolvedConflicts) {
    5458            if (!ds.getConflicts().hasConflictForMy(c.getMy())) {
    5559                ds.getConflicts().add(c);
     
    6165    public void undoCommand() {
    6266        super.undoCommand();
    6367
    64         DataSet ds = getAffectedDataSet();
     68        DataSet ds = (DataSet) getAffectedDataSet();
    6569        if (!OsmDataManager.getInstance().containsDataSet(ds)) {
    6670            Logging.warn(tr("Cannot undo command ''{0}'' because layer ''{1}'' is not present any more",
    6771                    this.toString(),
  • src/org/openstreetmap/josm/data/osm/DataSet.java

     
    128128    private final CopyOnWriteArrayList<DataSetListener> listeners = new CopyOnWriteArrayList<>();
    129129
    130130    // provide means to highlight map elements that are not osm primitives
    131     private Collection<WaySegment> highlightedVirtualNodes = new LinkedList<>();
    132     private Collection<WaySegment> highlightedWaySegments = new LinkedList<>();
     131    private Collection<WaySegment<Node, Way>> highlightedVirtualNodes = new LinkedList<>();
     132    private Collection<WaySegment<Node, Way>> highlightedWaySegments = new LinkedList<>();
    133133    private final ListenerList<HighlightUpdateListener> highlightUpdateListeners = ListenerList.create();
    134134
    135135    // Number of open calls to beginUpdate
     
    539539        primitive.setDataset(null);
    540540    }
    541541
    542     void removePrimitive(OsmPrimitive primitive) {
     542    @Override
     543    public void removePrimitive(OsmPrimitive primitive) {
    543544        checkModifiable();
    544545        update(() -> {
    545546            removePrimitiveImpl(primitive);
     
    571572    }
    572573
    573574    @Override
    574     public Collection<WaySegment> getHighlightedVirtualNodes() {
     575    public Collection<WaySegment<Node, Way>> getHighlightedVirtualNodes() {
    575576        return Collections.unmodifiableCollection(highlightedVirtualNodes);
    576577    }
    577578
    578579    @Override
    579     public Collection<WaySegment> getHighlightedWaySegments() {
     580    public Collection<WaySegment<Node, Way>> getHighlightedWaySegments() {
    580581        return Collections.unmodifiableCollection(highlightedWaySegments);
    581582    }
    582583
     
    630631    }
    631632
    632633    @Override
    633     public void setHighlightedVirtualNodes(Collection<WaySegment> waySegments) {
     634    public void setHighlightedVirtualNodes(Collection<WaySegment<Node, Way>> waySegments) {
    634635        if (highlightedVirtualNodes.isEmpty() && waySegments.isEmpty())
    635636            return;
    636637
     
    639640    }
    640641
    641642    @Override
    642     public void setHighlightedWaySegments(Collection<WaySegment> waySegments) {
     643    public void setHighlightedWaySegments(Collection<WaySegment<Node, Way>> waySegments) {
    643644        if (highlightedWaySegments.isEmpty() && waySegments.isEmpty())
    644645            return;
    645646
  • src/org/openstreetmap/josm/data/osm/DefaultNameFormatter.java

     
    667667     * @param maxElements the maximum number of elements to display
    668668     * @return HTML unordered list
    669669     */
    670     public String formatAsHtmlUnorderedList(Collection<? extends OsmPrimitive> primitives, int maxElements) {
     670    public String formatAsHtmlUnorderedList(Collection<? extends IPrimitive> primitives, int maxElements) {
    671671        Collection<String> displayNames = primitives.stream().map(x -> x.getDisplayName(this)).collect(Collectors.toList());
    672672        return Utils.joinAsHtmlUnorderedList(Utils.limit(displayNames, maxElements, "..."));
    673673    }
  • src/org/openstreetmap/josm/data/osm/INode.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
    33
     4import org.openstreetmap.josm.data.Bounds;
    45import org.openstreetmap.josm.data.coor.EastNorth;
    56import org.openstreetmap.josm.data.coor.ILatLon;
    67import org.openstreetmap.josm.data.coor.LatLon;
     
    7071    default String getDisplayName(NameFormatter formatter) {
    7172        return formatter.format(this);
    7273    }
     74
     75
     76    /**
     77     * Determines if this node is outside of the world. See also #13538.
     78     * @return <code>true</code>, if the coordinate is outside the world, compared by using lat/lon and east/north
     79     * @since 14960 (extracted to INode in xxx)
     80     */
     81    default public boolean isOutSideWorld() {
     82        LatLon ll = getCoor();
     83        if (ll != null) {
     84            Bounds b = ProjectionRegistry.getProjection().getWorldBoundsLatLon();
     85            if (lat() < b.getMinLat() || lat() > b.getMaxLat() || lon() < b.getMinLon() || lon() > b.getMaxLon()) {
     86                return true;
     87            }
     88            if (!ProjectionRegistry.getProjection().latlon2eastNorth(ll).equalsEpsilon(getEastNorth(), 1.0)) {
     89                // we get here if a node was moved or created left from -180 or right from +180
     90                return true;
     91            }
     92        }
     93        return false;
     94    }
    7395}
  • src/org/openstreetmap/josm/data/osm/IPrimitive.java

     
    331331     * Makes the given visitor visit this primitive.
    332332     * @param visitor visitor
    333333     */
    334     void accept(PrimitiveVisitor visitor);
     334    void accept(PrimitiveVisitor<?, ?, ?> visitor);
    335335
    336336    /**
    337337     * <p>Visits {@code visitor} for all referrers.</p>
     
    339339     * @param visitor the visitor. Ignored, if null.
    340340     * @since 13806
    341341     */
    342     void visitReferrers(PrimitiveVisitor visitor);
     342    void visitReferrers(PrimitiveVisitor<?, ?, ?> visitor);
    343343
    344344    /**
    345345     * Replies the name of this primitive. The default implementation replies the value
     
    478478     * @return OsmData this primitive is part of.
    479479     * @since 13807
    480480     */
    481     OsmData<?, ?, ?, ?> getDataSet();
     481    <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> OsmData<O, N, W, R> getDataSet();
    482482
    483483    /**
    484484     * Returns {@link #getKeys()} for which {@code key} does not fulfill uninteresting criteria.
  • src/org/openstreetmap/josm/data/osm/IRelation.java

     
    1414 * @param <M> Type of OSM relation member
    1515 * @since 4098
    1616 */
    17 public interface IRelation<M extends IRelationMember<?>> extends IPrimitive {
     17public interface IRelation<M extends IRelationMember<?, ?, ?, ?>> extends IPrimitive {
    1818
    1919    /**
    2020     * Returns the number of members.
  • src/org/openstreetmap/josm/data/osm/IRelationMember.java

     
    55
    66/**
    77 * IRelationMember captures the common functions of {@link RelationMember} and {@link RelationMemberData}.
    8  * @param <P> the base type of OSM primitives
     8 * @param <O> the base type of primitives
     9 * @param <N> type representing nodes
     10 * @param <W> type representing ways
     11 * @param <R> type representing relations
    912 * @since 13677
    1013 */
    11 public interface IRelationMember<P extends IPrimitive> extends PrimitiveId {
     14public interface IRelationMember<O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> extends PrimitiveId {
    1215
    1316    /**
    1417     * Returns the role of this relation member.
     
    4043    boolean isNode();
    4144
    4245    /**
     46     * Returns the relation member as a node.
     47     * @return Member as node
     48     * @since 1937 (RelationMember), xxx (IRelationMember)
     49     */
     50    N getNode();
     51
     52    /**
    4353     * Determines if this relation member is a way.
    4454     * @return True if member is way
    4555     */
     
    4656    boolean isWay();
    4757
    4858    /**
     59     * Returns the relation member as a way.
     60     * @return Member as way
     61     * @since 1937 (RelationMember), xxx (IRelationMember)
     62     */
     63    W getWay();
     64
     65    /**
    4966     * Determines if this relation member is a relation.
    5067     * @return True if member is relation
    5168     */
     
    5269    boolean isRelation();
    5370
    5471    /**
     72     * Returns the relation member as a relation.
     73     * @return Member as relation
     74     * @since 1937 (RelationMember), xxx (IRelationMember)
     75     */
     76    R getRelation();
     77
     78    /**
    5579     * Returns type of member for icon display.
    5680     * @return type of member for icon display
    5781     * @since 13766 (IRelationMember)
     
    6589     * @return Member. Returned value is never null.
    6690     * @since 13766 (IRelationMember)
    6791     */
    68     P getMember();
     92    O getMember();
    6993}
  • src/org/openstreetmap/josm/data/osm/IWay.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
    33
     4import java.util.Collection;
    45import java.util.List;
    56
     7import org.openstreetmap.josm.tools.Pair;
     8
    69/**
    710 * IWay captures the common functions of {@link Way} and {@link WayData}.
    811 * @param <N> type of OSM node
     
    132135     * @since 13922
    133136     */
    134137    boolean isInnerNode(INode n);
     138
     139    /**
     140     * Removes the given {@link Node} from this way. Ignored, if n is null.
     141     * @param n The node to remove. Ignored, if null
     142     * @since 1463 Way, xxx IWay
     143     */
     144    public void removeNode(N n);
     145
     146    /**
     147     * Removes the given set of {@link Node nodes} from this way. Ignored, if selection is null.
     148     * @param selection The selection of nodes to remove. Ignored, if null
     149     * @since 5408 Way, xxx IWay
     150     */
     151    public void removeNodes(Collection<N> selection);
     152
     153    /**
     154     * Adds a node to the end of the list of nodes. Ignored, if n is null.
     155     *
     156     * @param n the node. Ignored, if null
     157     * @throws IllegalStateException if this way is marked as incomplete. We can't add a node
     158     * to an incomplete way
     159     * @since 1313 Way, xxx IWay
     160     */
     161    void addNode(N n);
     162
     163    /**
     164     * Adds a node at position offs.
     165     *
     166     * @param offs the offset
     167     * @param n the node. Ignored, if null.
     168     * @throws IllegalStateException if this way is marked as incomplete. We can't add a node
     169     * to an incomplete way
     170     * @throws IndexOutOfBoundsException if offs is out of bounds
     171     * @since 1313 Way, xxx IWay
     172     */
     173    void addNode(int offs, N n);
     174
     175    /**
     176     * Replies the ordered {@link List} of chunks of this way. Each chunk is replied as a {@link Pair} of {@link Node nodes}.
     177     * @param sort If true, the nodes of each pair are sorted as defined by {@link Pair#sort}.
     178     *             If false, Pair.a and Pair.b are in the way order
     179     *             (i.e for a given Pair(n), Pair(n-1).b == Pair(n).a, Pair(n).b == Pair(n+1).a, etc.)
     180     * @return The ordered list of chunks of this way.
     181     * @since 3348 (Way), xxx (IWay)
     182     */
     183    List<Pair<N, N>> getNodePairs(boolean sort);
    135184}
  • src/org/openstreetmap/josm/data/osm/Node.java

     
    1010import java.util.function.Predicate;
    1111import java.util.stream.Collectors;
    1212
    13 import org.openstreetmap.josm.data.Bounds;
    1413import org.openstreetmap.josm.data.coor.EastNorth;
    1514import org.openstreetmap.josm.data.coor.LatLon;
    1615import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;
     
    405404        return referrers(Way.class).collect(Collectors.toList());
    406405    }
    407406
    408     /**
    409      * Determines if this node is outside of the world. See also #13538.
    410      * @return <code>true</code>, if the coordinate is outside the world, compared by using lat/lon and east/north
    411      * @since 14960
    412      */
    413     public boolean isOutSideWorld() {
    414         LatLon ll = getCoor();
    415         if (ll != null) {
    416             Bounds b = ProjectionRegistry.getProjection().getWorldBoundsLatLon();
    417             if (lat() < b.getMinLat() || lat() > b.getMaxLat() || lon() < b.getMinLon() || lon() > b.getMaxLon()) {
    418                 return true;
    419             }
    420             if (!ProjectionRegistry.getProjection().latlon2eastNorth(ll).equalsEpsilon(getEastNorth(), 1.0)) {
    421                 // we get here if a node was moved or created left from -180 or right from +180
    422                 return true;
    423             }
    424         }
    425         return false;
    426     }
    427 
    428407    @Override
    429408    public UniqueIdGenerator getIdGenerator() {
    430409        return idGenerator;
  • src/org/openstreetmap/josm/data/osm/NodePositionComparator.java

     
    99 *
    1010 * @author viesturs
    1111 */
    12 public class NodePositionComparator implements Comparator<Node>, Serializable {
     12public class NodePositionComparator<N extends INode> implements Comparator<N>, Serializable {
    1313
    1414    private static final long serialVersionUID = 1L;
    1515
    1616    @Override
    17     public int compare(Node n1, Node n2) {
     17    public int compare(N n1, N n2) {
    1818
    1919        if (n1.getCoor().equalsEpsilon(n2.getCoor()))
    2020            return 0;
  • src/org/openstreetmap/josm/data/osm/OsmData.java

     
    6161    void addPrimitive(O primitive);
    6262
    6363    /**
     64     * Removes a primitive
     65     * @param primitive the primitive
     66     */
     67    void removePrimitive(O primitive);
     68
     69    /**
    6470     * Removes all primitives.
    6571     */
    6672    void clear();
     
    269275     *
    270276     * @return unmodifiable collection of WaySegments
    271277     */
    272     Collection<WaySegment> getHighlightedVirtualNodes();
     278    Collection<WaySegment<N, W>> getHighlightedVirtualNodes();
    273279
    274280    /**
    275281     * Returns an unmodifiable collection of WaySegments that should be highlighted.
     
    276282     *
    277283     * @return unmodifiable collection of WaySegments
    278284     */
    279     Collection<WaySegment> getHighlightedWaySegments();
     285    Collection<WaySegment<N, W>> getHighlightedWaySegments();
    280286
    281287    /**
    282288     * clear all highlights of virtual nodes
    283289     */
    284290    default void clearHighlightedVirtualNodes() {
    285         setHighlightedVirtualNodes(new ArrayList<WaySegment>());
     291        setHighlightedVirtualNodes(new ArrayList<WaySegment<N, W>>());
    286292    }
    287293
    288294    /**
     
    289295     * clear all highlights of way segments
    290296     */
    291297    default void clearHighlightedWaySegments() {
    292         setHighlightedWaySegments(new ArrayList<WaySegment>());
     298        setHighlightedWaySegments(new ArrayList<WaySegment<N, W>>());
    293299    }
    294300
    295301    /**
     
    297303     * *WaySegments* to avoid a VirtualNode class that wouldn't have much use otherwise.
    298304     * @param waySegments Collection of way segments
    299305     */
    300     void setHighlightedVirtualNodes(Collection<WaySegment> waySegments);
     306    void setHighlightedVirtualNodes(Collection<WaySegment<N, W>> waySegments);
    301307
    302308    /**
    303309     * set what virtual ways should be highlighted.
    304310     * @param waySegments Collection of way segments
    305311     */
    306     void setHighlightedWaySegments(Collection<WaySegment> waySegments);
     312    void setHighlightedWaySegments(Collection<WaySegment<N, W>> waySegments);
    307313
    308314    /**
    309315     * Adds a listener that gets notified whenever way segment / virtual nodes highlights change.
  • src/org/openstreetmap/josm/data/osm/PrimitiveData.java

     
    168168    }
    169169
    170170    @Override
    171     public OsmData<?, ?, ?, ?> getDataSet() {
     171    public <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> OsmData<O, N, W, R> getDataSet() {
    172172        return null;
    173173    }
    174174
  • src/org/openstreetmap/josm/data/osm/RelationMember.java

     
    1111 * Since membership may be qualified by a "role", a simple list is not sufficient.
    1212 * @since 343
    1313 */
    14 public class RelationMember implements IRelationMember<OsmPrimitive> {
     14public class RelationMember implements IRelationMember<OsmPrimitive, Node, Way, Relation> {
    1515
    1616    /**
    1717     *
     
    6666     * @return Member as node
    6767     * @since 1937
    6868     */
     69    @Override
    6970    public Node getNode() {
    7071        return (Node) member;
    7172    }
  • src/org/openstreetmap/josm/data/osm/Way.java

     
    55
    66import java.util.ArrayList;
    77import java.util.Arrays;
     8import java.util.Collection;
    89import java.util.HashSet;
    910import java.util.List;
    1011import java.util.Map;
     
    151152        return neigh;
    152153    }
    153154
    154     /**
    155      * Replies the ordered {@link List} of chunks of this way. Each chunk is replied as a {@link Pair} of {@link Node nodes}.
    156      * @param sort If true, the nodes of each pair are sorted as defined by {@link Pair#sort}.
    157      *             If false, Pair.a and Pair.b are in the way order
    158      *             (i.e for a given Pair(n), Pair(n-1).b == Pair(n).a, Pair(n).b == Pair(n+1).a, etc.)
    159      * @return The ordered list of chunks of this way.
    160      * @since 3348
    161      */
     155    @Override
    162156    public List<Pair<Node, Node>> getNodePairs(boolean sort) {
    163157        List<Pair<Node, Node>> chunkSet = new ArrayList<>();
    164158        if (isIncomplete()) return chunkSet;
     
    182176        visitor.visit(this);
    183177    }
    184178
    185     @Override public void accept(PrimitiveVisitor visitor) {
     179    @Override public void accept(PrimitiveVisitor<?, ?, ?> visitor) {
    186180        visitor.visit(this);
    187181    }
    188182
     
    332326        return true;
    333327    }
    334328
    335     /**
    336      * Removes the given {@link Node} from this way. Ignored, if n is null.
    337      * @param n The node to remove. Ignored, if null
    338      * @since 1463
    339      */
     329    @Override
    340330    public void removeNode(Node n) {
    341331        checkDatasetNotReadOnly();
    342332        if (n == null || isIncomplete()) return;
     
    361351        }
    362352    }
    363353
    364     /**
    365      * Removes the given set of {@link Node nodes} from this way. Ignored, if selection is null.
    366      * @param selection The selection of nodes to remove. Ignored, if null
    367      * @since 5408
    368      */
    369     public void removeNodes(Set<? extends Node> selection) {
     354    @Override
     355    public void removeNodes(Collection<Node> selection) {
    370356        checkDatasetNotReadOnly();
    371357        if (selection == null || isIncomplete()) return;
    372358        boolean locked = writeLock();
     
    395381        }
    396382    }
    397383
    398     /**
    399      * Adds a node to the end of the list of nodes. Ignored, if n is null.
    400      *
    401      * @param n the node. Ignored, if null
    402      * @throws IllegalStateException if this way is marked as incomplete. We can't add a node
    403      * to an incomplete way
    404      * @since 1313
    405      */
     384    @Override
    406385    public void addNode(Node n) {
    407386        checkDatasetNotReadOnly();
    408387        if (n == null) return;
     
    421400        }
    422401    }
    423402
    424     /**
    425      * Adds a node at position offs.
    426      *
    427      * @param offs the offset
    428      * @param n the node. Ignored, if null.
    429      * @throws IllegalStateException if this way is marked as incomplete. We can't add a node
    430      * to an incomplete way
    431      * @throws IndexOutOfBoundsException if offs is out of bounds
    432      * @since 1313
    433      */
     403    @Override
    434404    public void addNode(int offs, Node n) {
    435405        checkDatasetNotReadOnly();
    436406        if (n == null) return;
  • src/org/openstreetmap/josm/data/osm/WaySegment.java

     
    22package org.openstreetmap.josm.data.osm;
    33
    44import java.awt.geom.Line2D;
     5import java.lang.reflect.InvocationTargetException;
    56import java.util.Objects;
    67
     8import org.openstreetmap.josm.tools.Logging;
     9
    710/**
    811 * A segment consisting of 2 consecutive nodes out of a way.
    912 */
    10 public final class WaySegment implements Comparable<WaySegment> {
     13public final class WaySegment<N extends INode, W extends IWay<N>> implements Comparable<WaySegment<N, W>> {
    1114
    1215    /**
    1316     * The way.
    1417     */
    15     public final Way way;
     18    public final W way;
    1619
    1720    /**
    1821     * The index of one of the 2 nodes in the way.  The other node has the
     
    2629     * @param i The node lower index
    2730     * @throws IllegalArgumentException in case of invalid index
    2831     */
    29     public WaySegment(Way w, int i) {
     32    public WaySegment(W w, int i) {
    3033        way = w;
    3134        lowerIndex = i;
    3235        if (i < 0 || i >= w.getNodesCount() - 1) {
     
    3841     * Returns the first node of the way segment.
    3942     * @return the first node
    4043     */
    41     public Node getFirstNode() {
     44    public N getFirstNode() {
    4245        return way.getNode(lowerIndex);
    4346    }
    4447
     
    4649     * Returns the second (last) node of the way segment.
    4750     * @return the second node
    4851     */
    49     public Node getSecondNode() {
     52    public N getSecondNode() {
    5053        return way.getNode(lowerIndex + 1);
    5154    }
    5255
     
    5861     * @return way segment
    5962     * @throws IllegalArgumentException if the node pair is not part of way
    6063     */
    61     public static WaySegment forNodePair(Way way, Node first, Node second) {
     64    public static <N extends INode, W extends IWay<N>> WaySegment<N, W> forNodePair(W way, N first, N second) {
    6265        int endIndex = way.getNodesCount() - 1;
    6366        while (endIndex > 0) {
    6467            final int indexOfFirst = way.getNodes().subList(0, endIndex).lastIndexOf(first);
    6568            if (second.equals(way.getNode(indexOfFirst + 1))) {
    66                 return new WaySegment(way, indexOfFirst);
     69                return new WaySegment<>(way, indexOfFirst);
    6770            }
    6871            endIndex--;
    6972        }
     
    7275
    7376    /**
    7477     * Returns this way segment as complete way.
    75      * @return the way segment as {@code Way}
     78     * @return the way segment as {@code W}
    7679     */
    77     public Way toWay() {
    78         Way w = new Way();
    79         w.addNode(getFirstNode());
    80         w.addNode(getSecondNode());
    81         return w;
     80    public W toWay() {
     81        try {
     82            /** way is of type W, so it should always create a new W */
     83            @SuppressWarnings("unchecked")
     84            W w = (W) way.getClass().getConstructor().newInstance();
     85            w.addNode(getFirstNode());
     86            w.addNode(getSecondNode());
     87            return w;
     88        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
     89                | NoSuchMethodException | SecurityException e) {
     90            Logging.trace(e);
     91            return null;
     92        }
    8293    }
    8394
    8495    @Override
     
    8596    public boolean equals(Object o) {
    8697        if (this == o) return true;
    8798        if (o == null || getClass() != o.getClass()) return false;
    88         WaySegment that = (WaySegment) o;
     99        WaySegment<?, ?> that = (WaySegment<?, ?>) o;
    89100        return lowerIndex == that.lowerIndex &&
    90101                Objects.equals(way, that.way);
    91102    }
     
    96107    }
    97108
    98109    @Override
    99     public int compareTo(WaySegment o) {
     110    public int compareTo(WaySegment<N, W> o) {
    100111        return o == null ? -1 : (equals(o) ? 0 : toWay().compareTo(o.toWay()));
    101112    }
    102113
  • src/org/openstreetmap/josm/data/osm/visitor/AllNodesVisitor.java

     
    44import java.util.Collection;
    55import java.util.HashSet;
    66
    7 import org.openstreetmap.josm.data.osm.Node;
    8 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    9 import org.openstreetmap.josm.data.osm.Relation;
    10 import org.openstreetmap.josm.data.osm.RelationMember;
    11 import org.openstreetmap.josm.data.osm.Way;
     7import org.openstreetmap.josm.data.osm.INode;
     8import org.openstreetmap.josm.data.osm.IPrimitive;
     9import org.openstreetmap.josm.data.osm.IRelation;
     10import org.openstreetmap.josm.data.osm.IRelationMember;
     11import org.openstreetmap.josm.data.osm.IWay;
    1212
    1313/**
    1414 * Collect all nodes a specific osm primitive has.
     
    1515 *
    1616 * @author imi
    1717 */
    18 public class AllNodesVisitor implements OsmPrimitiveVisitor {
     18public class AllNodesVisitor<N extends INode, W extends IWay<N>, R extends IRelation<? extends IRelationMember<?, N, W, R>>> implements PrimitiveVisitor<N, W, R> {
    1919
    2020    /**
    2121     * The resulting nodes collected so far.
    2222     */
    23     public Collection<Node> nodes = new HashSet<>();
     23    public Collection<N> nodes = new HashSet<>();
    2424
    2525    /**
    2626     * Nodes have only itself as nodes.
    2727     */
    2828    @Override
    29     public void visit(Node n) {
     29    public void visit(N n) {
    3030        nodes.add(n);
    3131    }
    3232
     
    3434     * Ways have their way nodes.
    3535     */
    3636    @Override
    37     public void visit(Way w) {
     37    public void visit(W w) {
    3838        if (w.isIncomplete()) return;
    39         for (Node n : w.getNodes()) {
     39        for (N n : w.getNodes()) {
    4040            visit(n);
    4141        }
    4242    }
     
    4747     * if so, use AutomatchVisitor!
    4848     */
    4949    @Override
    50     public void visit(Relation e) {
    51         for (RelationMember m : e.getMembers()) {
     50    public void visit(R e) {
     51        for (IRelationMember<?, N, W, R> m : e.getMembers()) {
    5252            if (m.isNode()) visit(m.getNode());
    5353        }
    5454    }
     
    5858     * @param osms The OSM primitives to inspect
    5959     * @return All nodes the given primitives have.
    6060     */
    61     public static Collection<Node> getAllNodes(Collection<? extends OsmPrimitive> osms) {
    62         AllNodesVisitor v = new AllNodesVisitor();
    63         for (OsmPrimitive osm : osms) {
     61    public static <N extends INode, W extends IWay<N>, R extends IRelation<? extends IRelationMember<?, N, W, R>>> Collection<N> getAllNodes(Collection<? extends IPrimitive> osms) {
     62        AllNodesVisitor<N, W, R> v = new AllNodesVisitor<>();
     63        for (IPrimitive osm : osms) {
    6464            osm.accept(v);
    6565        }
    6666        return v.nodes;
  • src/org/openstreetmap/josm/data/osm/visitor/BoundingXYVisitor.java

     
    1414import org.openstreetmap.josm.data.osm.IRelation;
    1515import org.openstreetmap.josm.data.osm.IRelationMember;
    1616import org.openstreetmap.josm.data.osm.IWay;
    17 import org.openstreetmap.josm.data.osm.Node;
    1817import org.openstreetmap.josm.data.osm.OsmPrimitive;
    19 import org.openstreetmap.josm.data.osm.Relation;
    20 import org.openstreetmap.josm.data.osm.Way;
    2118import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    2219import org.openstreetmap.josm.spi.preferences.Config;
    2320
     
    2623 * EastNorth values as reference.
    2724 * @author imi
    2825 */
    29 public class BoundingXYVisitor implements OsmPrimitiveVisitor, PrimitiveVisitor {
     26public class BoundingXYVisitor implements PrimitiveVisitor<INode, IWay<INode>, IRelation<?>> {
    3027    /** default value for setting "edit.zoom-enlarge-bbox" */
    3128    private static final double ENLARGE_DEFAULT = 0.0002;
    3229
     
    3330    private ProjectionBounds bounds;
    3431
    3532    @Override
    36     public void visit(Node n) {
    37         visit((ILatLon) n);
    38     }
    39 
    40     @Override
    41     public void visit(Way w) {
    42         visit((IWay<?>) w);
    43     }
    44 
    45     @Override
    46     public void visit(Relation r) {
    47         visit((IRelation<?>) r);
    48     }
    49 
    50     @Override
    5133    public void visit(INode n) {
    5234        visit((ILatLon) n);
    5335    }
    5436
    5537    @Override
    56     public void visit(IWay<?> w) {
     38    public void visit(IWay<INode> w) {
    5739        if (w.isIncomplete()) return;
    5840        for (INode n : w.getNodes()) {
    5941            visit(n);
     
    6345    @Override
    6446    public void visit(IRelation<?> r) {
    6547        // only use direct members
    66         for (IRelationMember<?> m : r.getMembers()) {
     48        for (IRelationMember<?, ?, ?, ?> m : r.getMembers()) {
    6749            if (!m.isRelation()) {
    6850                m.getMember().accept(this);
    6951            }
  • src/org/openstreetmap/josm/data/osm/visitor/OsmPrimitiveVisitor.java

     
    1010 * types {@link Node}, {@link Way} and {@link Relation}.
    1111 * @since 12810
    1212 */
    13 public interface OsmPrimitiveVisitor {
     13public interface OsmPrimitiveVisitor extends PrimitiveVisitor<Node, Way, Relation> {
    1414    /**
    1515     * Visiting call for points.
    1616     * @param n The node to inspect.
    1717     */
     18    @Override
    1819    void visit(Node n);
    1920
    2021    /**
     
    2223     * @param w The way to inspect.
    2324     * @since 64
    2425     */
     26    @Override
    2527    void visit(Way w);
    2628
    2729    /**
     
    2931     * @param r The relation to inspect.
    3032     * @since 343
    3133     */
     34    @Override
    3235    void visit(Relation r);
    3336
    3437}
  • src/org/openstreetmap/josm/data/osm/visitor/PrimitiveVisitor.java

     
    77
    88/**
    99 * OSM primitives interfaces visitor, following conventional <a href="https://en.wikipedia.org/wiki/Visitor_pattern">visitor design pattern</a>.
    10  * @since 4100
     10 * @since 4100, xxx for generics
    1111 */
    12 public interface PrimitiveVisitor {
     12public interface PrimitiveVisitor<N extends INode, W extends IWay<N>, R extends IRelation<?>> {
    1313
    1414    /**
    1515     * Visiting call for nodes.
    1616     * @param n The node to inspect.
    1717     */
    18     void visit(INode n);
     18    void visit(N n);
    1919
    2020    /**
    2121     * Visiting call for ways.
    2222     * @param w The way to inspect.
    2323     */
    24     void visit(IWay<?> w);
     24    void visit(W w);
    2525
    2626    /**
    2727     * Visiting call for relations.
    2828     * @param r The relation to inspect.
    2929     */
    30     void visit(IRelation<?> r);
     30    void visit(R r);
    3131}
  • src/org/openstreetmap/josm/data/validation/Test.java

     
    282282     * @param testError error to fix
    283283     * @return The command to fix the error
    284284     */
    285     public Command fixError(TestError testError) {
     285    public Command<OsmPrimitive, Node, Way, Relation> fixError(TestError testError) {
    286286        return null;
    287287    }
    288288
     
    334334     * @param primitives The primitives wanted for deletion
    335335     * @return a Delete command on all primitives that have not yet been deleted, or null otherwise
    336336     */
    337     protected final Command deletePrimitivesIfNeeded(Collection<? extends OsmPrimitive> primitives) {
     337    protected final Command<OsmPrimitive, Node, Way, Relation> deletePrimitivesIfNeeded(Collection<? extends OsmPrimitive> primitives) {
    338338        Collection<OsmPrimitive> primitivesToDelete = new ArrayList<>();
    339339        for (OsmPrimitive p : primitives) {
    340340            if (!p.isDeleted()) {
  • src/org/openstreetmap/josm/data/validation/TestError.java

     
    5151    /** If this error is selected */
    5252    private boolean selected;
    5353    /** Supplying a command to fix the error */
    54     private final Supplier<Command> fixingCommand;
     54    private final Supplier<Command<OsmPrimitive, Node, Way, Relation>> fixingCommand;
    5555
    5656    /**
    5757     * A builder for a {@code TestError}.
     
    6666        private String descriptionEn;
    6767        private Collection<? extends OsmPrimitive> primitives;
    6868        private Collection<?> highlighted;
    69         private Supplier<Command> fixingCommand;
     69        private Supplier<Command<OsmPrimitive, Node, Way, Relation>> fixingCommand;
    7070
    7171        Builder(Test tester, Severity severity, int code) {
    7272            this.tester = tester;
     
    172172         * @return {@code this}
    173173         * @see ValidatorVisitor#visit(WaySegment)
    174174         */
    175         public Builder highlightWaySegments(Collection<WaySegment> highlighted) {
     175        public Builder highlightWaySegments(Collection<WaySegment<Node, Way>> highlighted) {
    176176            CheckParameterUtil.ensureParameterNotNull(highlighted, "highlighted");
    177177            this.highlighted = highlighted;
    178178            return this;
     
    209209         * @param fixingCommand the fix supplier. Can be null
    210210         * @return {@code this}
    211211         */
    212         public Builder fix(Supplier<Command> fixingCommand) {
     212        public Builder fix(Supplier<Command<OsmPrimitive, Node, Way, Relation>> fixingCommand) {
    213213            CheckParameterUtil.ensureThat(this.fixingCommand == null, "fixingCommand already set");
    214214            this.fixingCommand = fixingCommand;
    215215            return this;
     
    409409     *
    410410     * @return The command to fix the error
    411411     */
    412     public Command getFix() {
     412    public Command<OsmPrimitive, Node, Way, Relation> getFix() {
    413413        // obtain fix from the error
    414         final Command fix = fixingCommand != null ? fixingCommand.get() : null;
     414        final Command<OsmPrimitive, Node, Way, Relation> fix = fixingCommand != null ? fixingCommand.get() : null;
    415415        if (fix != null) {
    416416            return fix;
    417417        }
     
    441441            if (o instanceof OsmPrimitive) {
    442442                v.visit((OsmPrimitive) o);
    443443            } else if (o instanceof WaySegment) {
    444                 v.visit((WaySegment) o);
     444                v.visit((WaySegment<Node, Way>) o);
    445445            } else if (o instanceof List<?>) {
    446446                v.visit((List<Node>) o);
    447447            } else if (o instanceof Area) {
  • src/org/openstreetmap/josm/data/validation/tests/CrossingWays.java

     
    1414import java.util.Set;
    1515
    1616import org.openstreetmap.josm.data.coor.EastNorth;
     17import org.openstreetmap.josm.data.osm.Node;
    1718import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1819import org.openstreetmap.josm.data.osm.OsmUtils;
    1920import org.openstreetmap.josm.data.osm.Relation;
     
    7576    }
    7677
    7778    /** All way segments, grouped by cells */
    78     private final Map<Point2D, List<WaySegment>> cellSegments = new HashMap<>(1000);
     79    private final Map<Point2D, List<WaySegment<Node, Way>>> cellSegments = new HashMap<>(1000);
    7980    /** The already detected ways in error */
    80     private final Map<List<Way>, List<WaySegment>> seenWays = new HashMap<>(50);
     81    private final Map<List<Way>, List<WaySegment<Node, Way>>> seenWays = new HashMap<>(50);
    8182
    8283    protected final int code;
    8384
     
    364365
    365366        int nodesSize = w.getNodesCount();
    366367        for (int i = 0; i < nodesSize - 1; i++) {
    367             final WaySegment es1 = new WaySegment(w, i);
     368            final WaySegment<Node, Way> es1 = new WaySegment<>(w, i);
    368369            final EastNorth en1 = es1.getFirstNode().getEastNorth();
    369370            final EastNorth en2 = es1.getSecondNode().getEastNorth();
    370371            if (en1 == null || en2 == null) {
     
    371372                Logging.warn("Crossing ways test skipped " + es1);
    372373                continue;
    373374            }
    374             for (List<WaySegment> segments : getSegments(cellSegments, en1, en2)) {
    375                 for (WaySegment es2 : segments) {
     375            for (List<WaySegment<Node, Way>> segments : getSegments(cellSegments, en1, en2)) {
     376                for (WaySegment<Node, Way> es2 : segments) {
    376377                    List<Way> prims;
    377                     List<WaySegment> highlight;
     378                    List<WaySegment<Node, Way>> highlight;
    378379
    379380                    if (!es1.intersects(es2) || ignoreWaySegmentCombination(es1.way, es2.way)) {
    380381                        continue;
     
    419420     * @param n2 The second EastNorth
    420421     * @return A list with all the cells the segment crosses
    421422     */
    422     public static List<List<WaySegment>> getSegments(Map<Point2D, List<WaySegment>> cellSegments, EastNorth n1, EastNorth n2) {
    423         List<List<WaySegment>> cells = new ArrayList<>();
     423    public static List<List<WaySegment<Node, Way>>> getSegments(Map<Point2D, List<WaySegment<Node, Way>>> cellSegments, EastNorth n1, EastNorth n2) {
     424        List<List<WaySegment<Node, Way>>> cells = new ArrayList<>();
    424425        for (Point2D cell : ValUtil.getSegmentCells(n1, n2, OsmValidator.getGridDetail())) {
    425426            cells.add(cellSegments.computeIfAbsent(cell, k -> new ArrayList<>()));
    426427        }
     
    434435     * @param crossingWays map to collect crossing ways and related segments
    435436     * @param findSharedWaySegments true: find shared way segments instead of crossings
    436437     */
    437     public static void findIntersectingWay(Way w, Map<Point2D, List<WaySegment>> cellSegments,
    438             Map<List<Way>, List<WaySegment>> crossingWays, boolean findSharedWaySegments) {
     438    public static void findIntersectingWay(Way w, Map<Point2D, List<WaySegment<Node, Way>>> cellSegments,
     439            Map<List<Way>, List<WaySegment<Node, Way>>> crossingWays, boolean findSharedWaySegments) {
    439440        int nodesSize = w.getNodesCount();
    440441        for (int i = 0; i < nodesSize - 1; i++) {
    441             final WaySegment es1 = new WaySegment(w, i);
     442            final WaySegment<Node, Way> es1 = new WaySegment<>(w, i);
    442443            final EastNorth en1 = es1.getFirstNode().getEastNorth();
    443444            final EastNorth en2 = es1.getSecondNode().getEastNorth();
    444445            if (en1 == null || en2 == null) {
     
    445446                Logging.warn("Crossing ways test skipped " + es1);
    446447                continue;
    447448            }
    448             for (List<WaySegment> segments : CrossingWays.getSegments(cellSegments, en1, en2)) {
    449                 for (WaySegment es2 : segments) {
     449            for (List<WaySegment<Node, Way>> segments : CrossingWays.getSegments(cellSegments, en1, en2)) {
     450                for (WaySegment<Node, Way> es2 : segments) {
    450451
    451                     List<WaySegment> highlight;
     452                    List<WaySegment<Node, Way>> highlight;
    452453                    if (es2.way == w // reported by CrossingWays.SelfIntersection
    453454                            || (findSharedWaySegments && !es1.isSimilar(es2))
    454455                            || (!findSharedWaySegments && !es1.intersects(es2)))
  • src/org/openstreetmap/josm/data/validation/tests/OverlappingWays.java

     
    4040public class OverlappingWays extends Test {
    4141
    4242    /** Bag of all way segments */
    43     private MultiMap<Pair<Node, Node>, WaySegment> nodePairs;
     43    private MultiMap<Pair<Node, Node>, WaySegment<Node, Way>> nodePairs;
    4444
    4545    protected static final int OVERLAPPING_HIGHWAY = 101;
    4646    protected static final int OVERLAPPING_RAILWAY = 102;
     
    7777
    7878    @Override
    7979    public void endTest() {
    80         Map<List<Way>, Set<WaySegment>> seenWays = new HashMap<>(500);
     80        Map<List<Way>, Set<WaySegment<Node, Way>>> seenWays = new HashMap<>(500);
    8181
    8282        Collection<TestError> preliminaryErrors = new ArrayList<>();
    83         for (Set<WaySegment> duplicated : nodePairs.values()) {
     83        for (Set<WaySegment<Node, Way>> duplicated : nodePairs.values()) {
    8484            int ways = duplicated.size();
    8585
    8686            if (ways > 1) {
    8787                List<OsmPrimitive> prims = new ArrayList<>();
    8888                List<Way> currentWays = new ArrayList<>();
    89                 Collection<WaySegment> highlight;
     89                Collection<WaySegment<Node, Way>> highlight;
    9090                int highway = 0;
    9191                int railway = 0;
    9292                int area = 0;
    9393
    94                 for (WaySegment ws : duplicated) {
     94                for (WaySegment<Node, Way> ws : duplicated) {
    9595                    if (ws.way.hasKey(HIGHWAY)) {
    9696                        highway++;
    9797                    } else if (ws.way.hasKey(RAILWAY)) {
     
    166166        nodePairs = null;
    167167    }
    168168
    169     protected static Set<WaySegment> checkDuplicateWaySegment(Way w) {
     169    protected static Set<WaySegment<Node, Way>> checkDuplicateWaySegment(Way w) {
    170170        // test for ticket #4959
    171         Set<WaySegment> segments = new TreeSet<>((o1, o2) -> {
     171        Set<WaySegment<Node, Way>> segments = new TreeSet<>((o1, o2) -> {
    172172            final List<Node> n1 = Arrays.asList(o1.getFirstNode(), o1.getSecondNode());
    173173            final List<Node> n2 = Arrays.asList(o2.getFirstNode(), o2.getSecondNode());
    174174            Collections.sort(n1);
     
    177177            final int second = n1.get(1).compareTo(n2.get(1));
    178178            return first != 0 ? first : second;
    179179        });
    180         final Set<WaySegment> duplicateWaySegments = new HashSet<>();
     180        final Set<WaySegment<Node, Way>> duplicateWaySegments = new HashSet<>();
    181181
    182182        for (int i = 0; i < w.getNodesCount() - 1; i++) {
    183             final WaySegment segment = new WaySegment(w, i);
     183            final WaySegment<Node, Way> segment = new WaySegment<>(w, i);
    184184            final boolean wasInSet = !segments.add(segment);
    185185            if (wasInSet) {
    186186                duplicateWaySegments.add(segment);
     
    192192    @Override
    193193    public void visit(Way w) {
    194194
    195         final Set<WaySegment> duplicateWaySegment = checkDuplicateWaySegment(w);
     195        final Set<WaySegment<Node, Way>> duplicateWaySegment = checkDuplicateWaySegment(w);
    196196        if (!duplicateWaySegment.isEmpty()) {
    197197            errors.add(TestError.builder(this, Severity.ERROR, DUPLICATE_WAY_SEGMENT)
    198198                    .message(tr("Way contains segment twice"))
     
    211211                continue;
    212212            }
    213213            nodePairs.put(Pair.sort(new Pair<>(lastN, n)),
    214                     new WaySegment(w, i));
     214                    new WaySegment<>(w, i));
    215215            lastN = n;
    216216        }
    217217    }
  • src/org/openstreetmap/josm/gui/NavigatableComponent.java

     
    3939import org.openstreetmap.josm.data.coor.ILatLon;
    4040import org.openstreetmap.josm.data.coor.LatLon;
    4141import org.openstreetmap.josm.data.osm.BBox;
    42 import org.openstreetmap.josm.data.osm.DataSet;
     42import org.openstreetmap.josm.data.osm.INode;
     43import org.openstreetmap.josm.data.osm.IPrimitive;
     44import org.openstreetmap.josm.data.osm.IRelation;
     45import org.openstreetmap.josm.data.osm.IWay;
    4346import org.openstreetmap.josm.data.osm.Node;
    44 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    45 import org.openstreetmap.josm.data.osm.Relation;
     47import org.openstreetmap.josm.data.osm.OsmData;
    4648import org.openstreetmap.josm.data.osm.Way;
    4749import org.openstreetmap.josm.data.osm.WaySegment;
    4850import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
     
    9092    /**
    9193     * To determine if a primitive is currently selectable.
    9294     */
    93     public transient Predicate<OsmPrimitive> isSelectablePredicate = prim -> {
     95    public transient Predicate<IPrimitive> isSelectablePredicate = prim -> {
    9496        if (!prim.isSelectable()) return false;
    9597        // if it isn't displayed on screen, you cannot click on it
    9698        MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().lock();
     
    549551     * @param n The node, where this geopoint would be drawn.
    550552     * @return The point on screen where "node" would be drawn, relative to the own top/left.
    551553     */
    552     public Point2D getPoint2D(Node n) {
     554    public Point2D getPoint2D(INode n) {
    553555        return getPoint2D(n.getEastNorth());
    554556    }
    555557
     
    590592     * looses precision, may overflow (depends on p and current scale)
    591593     * @param n node
    592594     * @return point
    593      * @see #getPoint2D(Node)
     595     * @see #getPoint2D(INode)
    594596     */
    595     public Point getPoint(Node n) {
     597    public Point getPoint(INode n) {
    596598        Point2D d = getPoint2D(n);
    597599        return new Point((int) d.getX(), (int) d.getY());
    598600    }
     
    982984     *
    983985     * @return a sorted map with the keys representing the distance of their associated nodes to point p.
    984986     */
    985     private Map<Double, List<Node>> getNearestNodesImpl(Point p, Predicate<OsmPrimitive> predicate) {
    986         Map<Double, List<Node>> nearestMap = new TreeMap<>();
    987         DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
     987    private Map<Double, List<INode>> getNearestNodesImpl(Point p, Predicate<IPrimitive> predicate) {
     988        Map<Double, List<INode>> nearestMap = new TreeMap<>();
     989        OsmData<?, ?, ?, ?> ds = MainApplication.getLayerManager().getActiveData();
    988990
    989991        if (ds != null) {
    990992            double dist, snapDistanceSq = PROP_SNAP_DISTANCE.get();
    991993            snapDistanceSq *= snapDistanceSq;
    992994
    993             for (Node n : ds.searchNodes(getBBox(p, PROP_SNAP_DISTANCE.get()))) {
     995            for (INode n : ds.searchNodes(getBBox(p, PROP_SNAP_DISTANCE.get()))) {
    994996                if (predicate.test(n)
    995997                        && (dist = getPoint2D(n).distanceSq(p)) < snapDistanceSq) {
    996998                    nearestMap.computeIfAbsent(dist, k -> new LinkedList<>()).add(n);
     
    10141016     *      dist(nearest) to dist(nearest)+4px around p and
    10151017     *      that are not in ignore.
    10161018     */
    1017     public final List<Node> getNearestNodes(Point p,
    1018             Collection<Node> ignore, Predicate<OsmPrimitive> predicate) {
    1019         List<Node> nearestList = Collections.emptyList();
     1019    public final List<INode> getNearestNodes(Point p,
     1020            Collection<INode> ignore, Predicate<IPrimitive> predicate) {
     1021        List<INode> nearestList = Collections.emptyList();
    10201022
    10211023        if (ignore == null) {
    10221024            ignore = Collections.emptySet();
    10231025        }
    10241026
    1025         Map<Double, List<Node>> nlists = getNearestNodesImpl(p, predicate);
     1027        Map<Double, List<INode>> nlists = getNearestNodesImpl(p, predicate);
    10261028        if (!nlists.isEmpty()) {
    10271029            Double minDistSq = null;
    1028             for (Entry<Double, List<Node>> entry : nlists.entrySet()) {
     1030            for (Entry<Double, List<INode>> entry : nlists.entrySet()) {
    10291031                Double distSq = entry.getKey();
    1030                 List<Node> nlist = entry.getValue();
     1032                List<INode> nlist = entry.getValue();
    10311033
    10321034                // filter nodes to be ignored before determining minDistSq..
    10331035                nlist.removeAll(ignore);
     
    10601062     *      dist(nearest) to dist(nearest)+4px around p.
    10611063     * @see #getNearestNodes(Point, Collection, Predicate)
    10621064     */
    1063     public final List<Node> getNearestNodes(Point p, Predicate<OsmPrimitive> predicate) {
     1065    public final List<INode> getNearestNodes(Point p, Predicate<IPrimitive> predicate) {
    10641066        return getNearestNodes(p, null, predicate);
    10651067    }
    10661068
     
    10841086     *
    10851087     * @return A node within snap-distance to point p, that is chosen by the algorithm described.
    10861088     */
    1087     public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate, boolean useSelected) {
     1089    public final INode getNearestNode(Point p, Predicate<IPrimitive> predicate, boolean useSelected) {
    10881090        return getNearestNode(p, predicate, useSelected, null);
    10891091    }
    10901092
     
    11121114     * @return A node within snap-distance to point p, that is chosen by the algorithm described.
    11131115     * @since 6065
    11141116     */
    1115     public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate,
    1116             boolean useSelected, Collection<OsmPrimitive> preferredRefs) {
     1117    public final INode getNearestNode(Point p, Predicate<IPrimitive> predicate,
     1118            boolean useSelected, Collection<IPrimitive> preferredRefs) {
    11171119
    1118         Map<Double, List<Node>> nlists = getNearestNodesImpl(p, predicate);
     1120        Map<Double, List<INode>> nlists = getNearestNodesImpl(p, predicate);
    11191121        if (nlists.isEmpty()) return null;
    11201122
    11211123        if (preferredRefs != null && preferredRefs.isEmpty()) preferredRefs = null;
    1122         Node ntsel = null, ntnew = null, ntref = null;
     1124        INode ntsel = null, ntnew = null, ntref = null;
    11231125        boolean useNtsel = useSelected;
    11241126        double minDistSq = nlists.keySet().iterator().next();
    11251127
    1126         for (Entry<Double, List<Node>> entry : nlists.entrySet()) {
     1128        for (Entry<Double, List<INode>> entry : nlists.entrySet()) {
    11271129            Double distSq = entry.getKey();
    1128             for (Node nd : entry.getValue()) {
     1130            for (INode nd : entry.getValue()) {
    11291131                // find the nearest selected node
    11301132                if (ntsel == null && nd.isSelected()) {
    11311133                    ntsel = nd;
     
    11361138                    useNtsel |= Utils.equalsEpsilon(distSq, minDistSq);
    11371139                }
    11381140                if (ntref == null && preferredRefs != null && Utils.equalsEpsilon(distSq, minDistSq)) {
    1139                     List<OsmPrimitive> ndRefs = nd.getReferrers();
    1140                     for (OsmPrimitive ref: preferredRefs) {
     1141                    List<? extends IPrimitive> ndRefs = nd.getReferrers();
     1142                    for (IPrimitive ref: preferredRefs) {
    11411143                        if (ndRefs.contains(ref)) {
    11421144                            ntref = nd;
    11431145                            break;
     
    11701172     *
    11711173     * @return The nearest node to point p.
    11721174     */
    1173     public final Node getNearestNode(Point p, Predicate<OsmPrimitive> predicate) {
     1175    public final INode getNearestNode(Point p, Predicate<IPrimitive> predicate) {
    11741176        return getNearestNode(p, predicate, true);
    11751177    }
    11761178
     
    11841186     * @return a sorted map with the keys representing the perpendicular
    11851187     *      distance of their associated way segments to point p.
    11861188     */
    1187     private Map<Double, List<WaySegment>> getNearestWaySegmentsImpl(Point p, Predicate<OsmPrimitive> predicate) {
    1188         Map<Double, List<WaySegment>> nearestMap = new TreeMap<>();
    1189         DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
     1189    private <N extends INode, W extends IWay<N>> Map<Double, List<WaySegment<N, W>>> getNearestWaySegmentsImpl(Point p, Predicate<IPrimitive> predicate, OsmData<?, N, W, ?> ds) {
     1190        Map<Double, List<WaySegment<N, W>>> nearestMap = new TreeMap<>();
    11901191
    11911192        if (ds != null) {
    11921193            double snapDistanceSq = Config.getPref().getInt("mappaint.segment.snap-distance", 10);
    11931194            snapDistanceSq *= snapDistanceSq;
    11941195
    1195             for (Way w : ds.searchWays(getBBox(p, Config.getPref().getInt("mappaint.segment.snap-distance", 10)))) {
     1196            for (W w : ds.searchWays(getBBox(p, Config.getPref().getInt("mappaint.segment.snap-distance", 10)))) {
    11961197                if (!predicate.test(w)) {
    11971198                    continue;
    11981199                }
    1199                 Node lastN = null;
     1200                N lastN = null;
    12001201                int i = -2;
    1201                 for (Node n : w.getNodes()) {
     1202                for (N n : w.getNodes()) {
    12021203                    i++;
    12031204                    if (n.isDeleted() || n.isIncomplete()) { //FIXME: This shouldn't happen, raise exception?
    12041205                        continue;
     
    12241225                            >> 32 << 32); // resolution in numbers with large exponent not needed here..
    12251226
    12261227                    if (perDistSq < snapDistanceSq && a < c + snapDistanceSq && b < c + snapDistanceSq) {
    1227                         nearestMap.computeIfAbsent(perDistSq, k -> new LinkedList<>()).add(new WaySegment(w, i));
     1228                        nearestMap.computeIfAbsent(perDistSq, k -> new LinkedList<>()).add(new WaySegment<>(w, i));
    12281229                    }
    12291230
    12301231                    lastN = n;
     
    12471248     * @return all segments within 10px of p that are not in ignore,
    12481249     *          sorted by their perpendicular distance.
    12491250     */
    1250     public final List<WaySegment> getNearestWaySegments(Point p,
    1251             Collection<WaySegment> ignore, Predicate<OsmPrimitive> predicate) {
    1252         List<WaySegment> nearestList = new ArrayList<>();
    1253         List<WaySegment> unselected = new LinkedList<>();
     1251    public final <N extends INode, W extends IWay<N>> List<WaySegment<N, W>> getNearestWaySegments(Point p,
     1252            Collection<WaySegment<N, W>> ignore, Predicate<IPrimitive> predicate) {
     1253        OsmData<?, N, W, ?> ds = MainApplication.getLayerManager().getActiveData();
     1254        List<WaySegment<N, W>> nearestList = new ArrayList<>();
     1255        List<WaySegment<N, W>> unselected = new LinkedList<>();
    12541256
    1255         for (List<WaySegment> wss : getNearestWaySegmentsImpl(p, predicate).values()) {
     1257        for (List<WaySegment<N, W>> wss : getNearestWaySegmentsImpl(p, predicate, ds).values()) {
    12561258            // put selected waysegs within each distance group first
    12571259            // makes the order of nearestList dependent on current selection state
    1258             for (WaySegment ws : wss) {
     1260            for (WaySegment<N, W> ws : wss) {
    12591261                (ws.way.isSelected() ? nearestList : unselected).add(ws);
    12601262            }
    12611263            nearestList.addAll(unselected);
     
    12771279     * @return all segments within 10px of p, sorted by their perpendicular distance.
    12781280     * @see #getNearestWaySegments(Point, Collection, Predicate)
    12791281     */
    1280     public final List<WaySegment> getNearestWaySegments(Point p, Predicate<OsmPrimitive> predicate) {
     1282    public final List<WaySegment<Node, Way>> getNearestWaySegments(Point p, Predicate<IPrimitive> predicate) {
    12811283        return getNearestWaySegments(p, null, predicate);
    12821284    }
    12831285
     
    12921294     *      and, depending on use_selected, prefers a selected way segment, if found.
    12931295     * @see #getNearestWaySegments(Point, Collection, Predicate)
    12941296     */
    1295     public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate, boolean useSelected) {
    1296         WaySegment wayseg = null;
    1297         WaySegment ntsel = null;
     1297    public final <N extends INode, W extends IWay<N>> WaySegment<N, W> getNearestWaySegment(Point p, Predicate<IPrimitive> predicate, boolean useSelected) {
     1298        OsmData<?, N, W, ?> ds = MainApplication.getLayerManager().getActiveData();
     1299        WaySegment<N, W> wayseg = null;
     1300        WaySegment<N, W> ntsel = null;
    12981301
    1299         for (List<WaySegment> wslist : getNearestWaySegmentsImpl(p, predicate).values()) {
     1302        for (List<WaySegment<N, W>> wslist : getNearestWaySegmentsImpl(p, predicate, ds).values()) {
    13001303            if (wayseg != null && ntsel != null) {
    13011304                break;
    13021305            }
    1303             for (WaySegment ws : wslist) {
     1306            for (WaySegment<N, W> ws : wslist) {
    13041307                if (wayseg == null) {
    13051308                    wayseg = ws;
    13061309                }
     
    13281331     * @see #getNearestWaySegments(Point, Collection, Predicate)
    13291332     * @since 6065
    13301333     */
    1331     public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate,
    1332             boolean useSelected, Collection<OsmPrimitive> preferredRefs) {
    1333         WaySegment wayseg = null;
     1334    public final <N extends INode, W extends IWay<N>> WaySegment<N, W> getNearestWaySegment(Point p, Predicate<IPrimitive> predicate,
     1335            boolean useSelected, Collection<IPrimitive> preferredRefs) {
     1336        OsmData<?, N, W, ?> ds = MainApplication.getLayerManager().getActiveData();
     1337        WaySegment<N, W> wayseg = null;
    13341338        if (preferredRefs != null && preferredRefs.isEmpty())
    13351339            preferredRefs = null;
    13361340
    1337         for (List<WaySegment> wslist : getNearestWaySegmentsImpl(p, predicate).values()) {
    1338             for (WaySegment ws : wslist) {
     1341        for (List<WaySegment<N, W>> wslist : getNearestWaySegmentsImpl(p, predicate, ds).values()) {
     1342            for (WaySegment<N, W> ws : wslist) {
    13391343                if (wayseg == null) {
    13401344                    wayseg = ws;
    13411345                }
     
    13471351                    if (preferredRefs.contains(ws.getFirstNode()) || preferredRefs.contains(ws.getSecondNode())) {
    13481352                        return ws;
    13491353                    }
    1350                     Collection<OsmPrimitive> wayRefs = ws.way.getReferrers();
     1354                    Collection<? extends IPrimitive> wayRefs = ws.way.getReferrers();
    13511355                    // prefer member of the given relations
    1352                     for (OsmPrimitive ref: preferredRefs) {
    1353                         if (ref instanceof Relation && wayRefs.contains(ref)) {
     1356                    for (IPrimitive ref: preferredRefs) {
     1357                        if (ref instanceof IRelation && wayRefs.contains(ref)) {
    13541358                            return ws;
    13551359                        }
    13561360                    }
     
    13671371     *
    13681372     * @return The nearest way segment to point p.
    13691373     */
    1370     public final WaySegment getNearestWaySegment(Point p, Predicate<OsmPrimitive> predicate) {
     1374    public final <N extends INode, W extends IWay<N>> WaySegment<N, W> getNearestWaySegment(Point p, Predicate<IPrimitive> predicate) {
    13711375        return getNearestWaySegment(p, predicate, true);
    13721376    }
    13731377
     
    13831387     * @return all nearest ways to the screen point given that are not in ignore.
    13841388     * @see #getNearestWaySegments(Point, Collection, Predicate)
    13851389     */
    1386     public final List<Way> getNearestWays(Point p,
    1387             Collection<Way> ignore, Predicate<OsmPrimitive> predicate) {
    1388         List<Way> nearestList = new ArrayList<>();
    1389         Set<Way> wset = new HashSet<>();
     1390    public final <N extends INode, W extends IWay<N>> List<W> getNearestWays(Point p,
     1391            Collection<W> ignore, Predicate<IPrimitive> predicate) {
     1392        OsmData<?, N, W, ?> ds = MainApplication.getLayerManager().getActiveData();
     1393        List<W> nearestList = new ArrayList<>();
     1394        Set<W> wset = new HashSet<>();
    13901395
    1391         for (List<WaySegment> wss : getNearestWaySegmentsImpl(p, predicate).values()) {
    1392             for (WaySegment ws : wss) {
     1396        for (List<WaySegment<N, W>> wss : getNearestWaySegmentsImpl(p, predicate, ds).values()) {
     1397            for (WaySegment<N, W> ws : wss) {
    13931398                if (wset.add(ws.way)) {
    13941399                    nearestList.add(ws.way);
    13951400                }
     
    14131418     * @return all nearest ways to the screen point given.
    14141419     * @see #getNearestWays(Point, Collection, Predicate)
    14151420     */
    1416     public final List<Way> getNearestWays(Point p, Predicate<OsmPrimitive> predicate) {
     1421    public final <N extends INode, W extends IWay<N>> List<W> getNearestWays(Point p, Predicate<IPrimitive> predicate) {
    14171422        return getNearestWays(p, null, predicate);
    14181423    }
    14191424
     
    14261431     * @return The nearest way to point p, prefer a selected way if there are multiple nearest.
    14271432     * @see #getNearestWaySegment(Point, Predicate)
    14281433     */
    1429     public final Way getNearestWay(Point p, Predicate<OsmPrimitive> predicate) {
    1430         WaySegment nearestWaySeg = getNearestWaySegment(p, predicate);
     1434    public final <N extends INode, W extends IWay<N>> W getNearestWay(Point p, Predicate<IPrimitive> predicate) {
     1435        WaySegment<N, W> nearestWaySeg = getNearestWaySegment(p, predicate);
    14311436        return (nearestWaySeg == null) ? null : nearestWaySeg.way;
    14321437    }
    14331438
     
    14521457     * @see #getNearestNodes(Point, Collection, Predicate)
    14531458     * @see #getNearestWays(Point, Collection, Predicate)
    14541459     */
    1455     public final List<OsmPrimitive> getNearestNodesOrWays(Point p,
    1456             Collection<OsmPrimitive> ignore, Predicate<OsmPrimitive> predicate) {
    1457         List<OsmPrimitive> nearestList = Collections.emptyList();
    1458         OsmPrimitive osm = getNearestNodeOrWay(p, predicate, false);
     1460    public final List<IPrimitive> getNearestNodesOrWays(Point p,
     1461            Collection<IPrimitive> ignore, Predicate<IPrimitive> predicate) {
     1462        List<IPrimitive> nearestList = Collections.emptyList();
     1463        IPrimitive osm = getNearestNodeOrWay(p, predicate, false);
    14591464
    14601465        if (osm != null) {
    1461             if (osm instanceof Node) {
     1466            if (osm instanceof INode) {
    14621467                nearestList = new ArrayList<>(getNearestNodes(p, predicate));
    1463             } else if (osm instanceof Way) {
     1468            } else if (osm instanceof IWay) {
    14641469                nearestList = new ArrayList<>(getNearestWays(p, predicate));
    14651470            }
    14661471            if (ignore != null) {
     
    14811486     * @return Primitives nearest to the given screen point.
    14821487     * @see #getNearestNodesOrWays(Point, Collection, Predicate)
    14831488     */
    1484     public final List<OsmPrimitive> getNearestNodesOrWays(Point p, Predicate<OsmPrimitive> predicate) {
     1489    public final List<IPrimitive> getNearestNodesOrWays(Point p, Predicate<IPrimitive> predicate) {
    14851490        return getNearestNodesOrWays(p, null, predicate);
    14861491    }
    14871492
     
    14941499     * @param useSelected whether to prefer selected nodes
    14951500     * @return true, if the node fulfills the properties of the function body
    14961501     */
    1497     private boolean isPrecedenceNode(Node osm, Point p, boolean useSelected) {
     1502    private boolean isPrecedenceNode(INode osm, Point p, boolean useSelected) {
    14981503        if (osm != null) {
    14991504            if (p.distanceSq(getPoint2D(osm)) <= (4*4)) return true;
    15001505            if (osm.isTagged()) return true;
     
    15271532     * @see #getNearestNode(Point, Predicate)
    15281533     * @see #getNearestWay(Point, Predicate)
    15291534     */
    1530     public final OsmPrimitive getNearestNodeOrWay(Point p, Predicate<OsmPrimitive> predicate, boolean useSelected) {
    1531         Collection<OsmPrimitive> sel;
    1532         DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
     1535    public final IPrimitive getNearestNodeOrWay(Point p, Predicate<IPrimitive> predicate, boolean useSelected) {
     1536        Collection<IPrimitive> sel;
     1537        OsmData<? extends IPrimitive, ? extends INode, ? extends IWay<?>, ? extends IRelation<?>> ds = MainApplication.getLayerManager().getActiveData();
    15331538        if (useSelected && ds != null) {
    1534             sel = ds.getSelected();
     1539            sel = new ArrayList<>(ds.getSelected());
    15351540        } else {
    15361541            sel = null;
    15371542        }
    1538         OsmPrimitive osm = getNearestNode(p, predicate, useSelected, sel);
     1543        IPrimitive osm = getNearestNode(p, predicate, useSelected, sel);
    15391544
    1540         if (isPrecedenceNode((Node) osm, p, useSelected)) return osm;
    1541         WaySegment ws;
     1545        if (isPrecedenceNode((INode) osm, p, useSelected)) return osm;
     1546        WaySegment<?, ?> ws;
    15421547        if (useSelected) {
    15431548            ws = getNearestWaySegment(p, predicate, useSelected, sel);
    15441549        } else {
     
    15591564            // is wayseg shorter than maxWaySegLenSq and
    15601565            // is p closer to the middle of wayseg  than  to the nearest node?
    15611566            if (wp1.distanceSq(wp2) < maxWaySegLenSq &&
    1562                     p.distanceSq(project(0.5, wp1, wp2)) < p.distanceSq(getPoint2D((Node) osm))) {
     1567                    p.distanceSq(project(0.5, wp1, wp2)) < p.distanceSq(getPoint2D((INode) osm))) {
    15631568                osm = ws.way;
    15641569            }
    15651570        }
     
    15961601     * @return a list of all objects that are nearest to point p and
    15971602     *          not in ignore or an empty list if nothing was found.
    15981603     */
    1599     public final List<OsmPrimitive> getAllNearest(Point p,
    1600             Collection<OsmPrimitive> ignore, Predicate<OsmPrimitive> predicate) {
    1601         List<OsmPrimitive> nearestList = new ArrayList<>();
    1602         Set<Way> wset = new HashSet<>();
     1604    public final List<IPrimitive> getAllNearest(Point p,
     1605            Collection<IPrimitive> ignore, Predicate<IPrimitive> predicate) {
     1606        List<IPrimitive> nearestList = new ArrayList<>();
     1607        Set<IWay<?>> wset = new HashSet<>();
    16031608
    16041609        // add nearby ways
    1605         for (List<WaySegment> wss : getNearestWaySegmentsImpl(p, predicate).values()) {
    1606             for (WaySegment ws : wss) {
     1610        for (List<WaySegment<INode, IWay<INode>>> wss : getNearestWaySegmentsImpl(p, predicate, MainApplication.getLayerManager().getActiveData()).values()) {
     1611            for (WaySegment<?, ?> ws : wss) {
    16071612                if (wset.add(ws.way)) {
    16081613                    nearestList.add(ws.way);
    16091614                }
     
    16111616        }
    16121617
    16131618        // add nearby nodes
    1614         for (List<Node> nlist : getNearestNodesImpl(p, predicate).values()) {
     1619        for (List<INode> nlist : getNearestNodesImpl(p, predicate).values()) {
    16151620            nearestList.addAll(nlist);
    16161621        }
    16171622
    16181623        // add parent relations of nearby nodes and ways
    1619         Set<OsmPrimitive> parentRelations = new HashSet<>();
    1620         for (OsmPrimitive o : nearestList) {
    1621             for (OsmPrimitive r : o.getReferrers()) {
    1622                 if (r instanceof Relation && predicate.test(r)) {
     1624        Set<IPrimitive> parentRelations = new HashSet<>();
     1625        for (IPrimitive o : nearestList) {
     1626            for (IPrimitive r : o.getReferrers()) {
     1627                if (r instanceof IRelation && predicate.test(r)) {
    16231628                    parentRelations.add(r);
    16241629                }
    16251630            }
     
    16441649     *          or an empty list if nothing was found.
    16451650     * @see #getAllNearest(Point, Collection, Predicate)
    16461651     */
    1647     public final List<OsmPrimitive> getAllNearest(Point p, Predicate<OsmPrimitive> predicate) {
     1652    public final List<IPrimitive> getAllNearest(Point p, Predicate<IPrimitive> predicate) {
    16481653        return getAllNearest(p, null, predicate);
    16491654    }
    16501655
  • src/org/openstreetmap/josm/gui/SelectionManager.java

     
    1919
    2020import org.openstreetmap.josm.actions.SelectByInternalPointAction;
    2121import org.openstreetmap.josm.data.Bounds;
    22 import org.openstreetmap.josm.data.osm.DataSet;
    23 import org.openstreetmap.josm.data.osm.Node;
    24 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    25 import org.openstreetmap.josm.data.osm.Way;
     22import org.openstreetmap.josm.data.osm.INode;
     23import org.openstreetmap.josm.data.osm.IPrimitive;
     24import org.openstreetmap.josm.data.osm.IWay;
     25import org.openstreetmap.josm.data.osm.OsmData;
    2626import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
    2727import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable;
    2828import org.openstreetmap.josm.tools.ColorHelper;
     
    363363     * objects that are touched, instead those which are completely covered.
    364364     * @return The collection of selected objects.
    365365     */
    366     public Collection<OsmPrimitive> getSelectedObjects(boolean alt) {
    367         Collection<OsmPrimitive> selection = new LinkedList<>();
     366    public Collection<IPrimitive> getSelectedObjects(boolean alt) {
     367        Collection<IPrimitive> selection = new LinkedList<>();
    368368
    369369        // whether user only clicked, not dragged.
    370370        boolean clicked = false;
     
    373373            clicked = true;
    374374        }
    375375
    376         DataSet ds = MainApplication.getLayerManager().getActiveDataSet();
     376        OsmData<?, ?, ?, ?> ds = MainApplication.getLayerManager().getActiveData();
    377377        if (clicked) {
    378378            Point center = new Point(selectionResult.xpoints[0], selectionResult.ypoints[0]);
    379             OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive::isSelectable, false);
     379            IPrimitive osm = nc.getNearestNodeOrWay(center, IPrimitive::isSelectable, false);
    380380            if (osm != null) {
    381381                selection.add(osm);
    382382            }
    383383        } else if (ds != null) {
    384384            // nodes
    385             for (Node n : ds.getNodes()) {
     385            for (INode n : ds.getNodes()) {
    386386                if (n.isSelectable() && selectionResult.contains(nc.getPoint2D(n))) {
    387387                    selection.add(n);
    388388                }
     
    389389            }
    390390
    391391            // ways
    392             for (Way w : ds.getWays()) {
     392            for (IWay<?> w : ds.getWays()) {
    393393                if (!w.isSelectable() || w.isEmpty()) {
    394394                    continue;
    395395                }
    396396                if (alt) {
    397                     for (Node n : w.getNodes()) {
     397                    for (INode n : w.getNodes()) {
    398398                        if (!n.isIncomplete() && selectionResult.contains(nc.getPoint2D(n))) {
    399399                            selection.add(w);
    400400                            break;
     
    402402                    }
    403403                } else {
    404404                    boolean allIn = true;
    405                     for (Node n : w.getNodes()) {
     405                    for (INode n : w.getNodes()) {
    406406                        if (!n.isIncomplete() && !selectionResult.contains(nc.getPoint(n))) {
    407407                            allIn = false;
    408408                            break;
  • src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDataText.java

     
    183183
    184184    void addRelationMembers(IRelation<?> r) {
    185185        add(trn("{0} Member: ", "{0} Members: ", r.getMembersCount(), r.getMembersCount()));
    186         for (IRelationMember<?> m : r.getMembers()) {
     186        for (IRelationMember<?, ?, ?, ?> m : r.getMembers()) {
    187187            s.append(INDENT).append(INDENT);
    188188            addHeadline(m.getMember());
    189189            s.append(tr(" as \"{0}\"", m.getRole()));
  • src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java

     
    4040import org.openstreetmap.josm.data.osm.DataSet;
    4141import org.openstreetmap.josm.data.osm.Node;
    4242import org.openstreetmap.josm.data.osm.OsmPrimitive;
     43import org.openstreetmap.josm.data.osm.Relation;
     44import org.openstreetmap.josm.data.osm.Way;
    4345import org.openstreetmap.josm.data.osm.WaySegment;
    4446import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
    4547import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter;
     
    632634        protected void fixError(TestError error) throws InterruptedException, InvocationTargetException {
    633635            if (error.isFixable()) {
    634636                if (error.getPrimitives().stream().noneMatch(p -> p.isDeleted() || p.getDataSet() == null)) {
    635                     final Command fixCommand = error.getFix();
     637                    final Command<OsmPrimitive, Node, Way, Relation> fixCommand = error.getFix();
    636638                    if (fixCommand != null) {
    637639                        SwingUtilities.invokeAndWait(fixCommand::executeCommand);
    638640                        fixCommands.add(fixCommand);
     
    712714    }
    713715
    714716    private static class AutofixCommand extends SequenceCommand {
    715         AutofixCommand(Collection<Command> sequenz) {
     717        AutofixCommand(Collection<Command<OsmPrimitive, Node, Way, Relation>> sequenz) {
    716718            super(tr("auto-fixed validator issues"), sequenz, true);
    717719            setSequenceComplete(true);
    718720        }
     
    719721
    720722        @Override
    721723        public void undoCommand() {
    722             getAffectedDataSet().update(super::undoCommand);
     724            ((DataSet) getAffectedDataSet()).update(super::undoCommand);
    723725        }
    724726
    725727        @Override
    726728        public boolean executeCommand() {
    727             return getAffectedDataSet().update(super::executeCommand);
     729            return ((DataSet) getAffectedDataSet()).update(super::executeCommand);
    728730        }
    729731    }
    730732
  • src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java

     
    546546        OsmDataLayer layer = MainApplication.getLayerManager().getActiveDataLayer();
    547547        if (!layer.isLocked()) {
    548548            List<RelationMember> members = new ArrayList<>();
    549             for (IRelationMember<?> rm : ((MemberInfo) membershipData.getValueAt(row, 1)).role) {
     549            for (IRelationMember<?, ?, ?, ?> rm : ((MemberInfo) membershipData.getValueAt(row, 1)).role) {
    550550                if (rm instanceof RelationMember) {
    551551                    members.add((RelationMember) rm);
    552552                }
     
    681681                    MemberInfo mi = Optional.ofNullable(roles.get(r)).orElseGet(() -> new MemberInfo(newSel));
    682682                    roles.put(r, mi);
    683683                    int i = 1;
    684                     for (IRelationMember<?> m : r.getMembers()) {
     684                    for (IRelationMember<?, ?, ?, ?> m : r.getMembers()) {
    685685                        if (m.getMember() == primitive) {
    686686                            mi.add(m, i);
    687687                        }
     
    942942    static final class TaggingPresetCommandHandler implements TaggingPresetHandler {
    943943        @Override
    944944        public void updateTags(List<Tag> tags) {
    945             Command command = TaggingPreset.createCommand(getSelection(), tags);
     945            Command<?, ?, ?, ?> command = TaggingPreset.createCommand(getSelection(), tags);
    946946            if (command != null) {
    947947                UndoRedoHandler.getInstance().add(command);
    948948            }
     
    10001000    }
    10011001
    10021002    static class MemberInfo {
    1003         private final List<IRelationMember<?>> role = new ArrayList<>();
     1003        private final List<IRelationMember<?, ?, ?, ?>> role = new ArrayList<>();
    10041004        private Set<IPrimitive> members = new HashSet<>();
    10051005        private List<Integer> position = new ArrayList<>();
    10061006        private Collection<? extends IPrimitive> selection;
     
    10111011            this.selection = selection;
    10121012        }
    10131013
    1014         void add(IRelationMember<?> r, Integer p) {
     1014        void add(IRelationMember<?, ?, ?, ?> r, Integer p) {
    10151015            role.add(r);
    10161016            members.add(r.getMember());
    10171017            position.add(p);
     
    10331033
    10341034        String getRoleString() {
    10351035            if (roleString == null) {
    1036                 for (IRelationMember<?> r : role) {
     1036                for (IRelationMember<?, ?, ?, ?> r : role) {
    10371037                    if (roleString == null) {
    10381038                        roleString = r.getRole();
    10391039                    } else if (!roleString.equals(r.getRole())) {
     
    11421142            for (OsmPrimitive primitive: OsmDataManager.getInstance().getInProgressSelection()) {
    11431143                rel.removeMembersFor(primitive);
    11441144            }
    1145             UndoRedoHandler.getInstance().add(new ChangeCommand(cur, rel));
     1145            UndoRedoHandler.getInstance().add(new ChangeCommand<>(cur, rel));
    11461146
    11471147            tagTable.clearSelection();
    11481148            if (nextRelation != null) {
  • src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

     
    5151import org.openstreetmap.josm.command.ChangeCommand;
    5252import org.openstreetmap.josm.command.Command;
    5353import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
     54import org.openstreetmap.josm.data.osm.Node;
    5455import org.openstreetmap.josm.data.osm.OsmPrimitive;
    5556import org.openstreetmap.josm.data.osm.Relation;
    5657import org.openstreetmap.josm.data.osm.RelationMember;
    5758import org.openstreetmap.josm.data.osm.Tag;
     59import org.openstreetmap.josm.data.osm.Way;
    5860import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
    5961import org.openstreetmap.josm.gui.MainApplication;
    6062import org.openstreetmap.josm.gui.MainMenu;
     
    903905     * @return The resulting command
    904906     * @throws IllegalArgumentException if orig is null
    905907     */
    906     public static Command addPrimitivesToRelation(final Relation orig, Collection<? extends OsmPrimitive> primitivesToAdd) {
     908    public static Command<OsmPrimitive, Node, Way, Relation> addPrimitivesToRelation(final Relation orig, Collection<? extends OsmPrimitive> primitivesToAdd) {
    907909        CheckParameterUtil.ensureParameterNotNull(orig, "orig");
    908910        try {
    909911            final Collection<TaggingPreset> presets = TaggingPresets.getMatchingPresets(
     
    922924                relation.addMember(new RelationMember(roles.size() == 1 ? roles.iterator().next() : "", p));
    923925                modified = true;
    924926            }
    925             return modified ? new ChangeCommand(orig, relation) : null;
     927            return modified ? new ChangeCommand<>(orig, relation) : null;
    926928        } catch (AddAbortException ign) {
    927929            Logging.trace(ign);
    928930            return null;
  • src/org/openstreetmap/josm/gui/layer/AbstractOsmDataLayer.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.layer;
    33
     4import org.openstreetmap.josm.data.osm.INode;
     5import org.openstreetmap.josm.data.osm.IPrimitive;
     6import org.openstreetmap.josm.data.osm.IRelation;
     7import org.openstreetmap.josm.data.osm.IWay;
    48import org.openstreetmap.josm.data.osm.OsmData;
    59
    610/**
     
    1721     * Returns the {@link OsmData} behind this layer.
    1822     * @return the {@link OsmData} behind this layer.
    1923     */
    20     public abstract OsmData<?, ?, ?, ?> getDataSet();
     24    public abstract <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> OsmData<O, N, W, R> getDataSet();
    2125
    2226    @Override
    2327    public void lock() {
  • src/org/openstreetmap/josm/gui/layer/MainLayerManager.java

     
    1414
    1515import org.openstreetmap.josm.data.gpx.GpxData;
    1616import org.openstreetmap.josm.data.osm.DataSet;
     17import org.openstreetmap.josm.data.osm.INode;
     18import org.openstreetmap.josm.data.osm.IPrimitive;
     19import org.openstreetmap.josm.data.osm.IRelation;
     20import org.openstreetmap.josm.data.osm.IWay;
    1721import org.openstreetmap.josm.data.osm.OsmData;
    1822import org.openstreetmap.josm.gui.MainApplication;
    1923import org.openstreetmap.josm.gui.io.AsynchronousUploadPrimitivesTask;
     
    406410     * @return That data set, <code>null</code> if there is no active data layer.
    407411     * @since 13926
    408412     */
    409     public synchronized OsmData<?, ?, ?, ?> getActiveData() {
     413    public synchronized  <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> OsmData<O, N, W, R> getActiveData() {
    410414        if (dataLayer != null) {
    411415            return dataLayer.getDataSet();
    412416        } else {
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java

     
    2424import org.openstreetmap.josm.data.osm.IRelation;
    2525import org.openstreetmap.josm.data.osm.IRelationMember;
    2626import org.openstreetmap.josm.data.osm.IWay;
     27import org.openstreetmap.josm.data.osm.Node;
    2728import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    2829import org.openstreetmap.josm.data.osm.OsmUtils;
    2930import org.openstreetmap.josm.data.osm.Relation;
     
    189190         * referrer was found.</p>
    190191         *
    191192         */
    192         private class MatchingReferrerFinder implements PrimitiveVisitor {
     193        private class MatchingReferrerFinder implements PrimitiveVisitor<INode, IWay<INode>, IRelation<?>> {
    193194            private final Environment e;
    194195
    195196            /**
     
    243244            }
    244245
    245246            @Override
    246             public void visit(IWay<?> w) {
     247            public void visit(IWay<INode> w) {
    247248                doVisit(w, w::getNodesCount, w::getNode);
    248249            }
    249250
     
    253254            }
    254255        }
    255256
    256         private abstract static class AbstractFinder implements PrimitiveVisitor {
     257        private abstract static class AbstractFinder implements PrimitiveVisitor<INode, IWay<INode>, IRelation<?>> {
    257258            protected final Environment e;
    258259
    259260            protected AbstractFinder(Environment e) {
     
    265266            }
    266267
    267268            @Override
    268             public void visit(IWay<?> w) {
     269            public void visit(IWay<INode> w) {
    269270            }
    270271
    271272            @Override
     
    298299        private class MultipolygonOpenEndFinder extends AbstractFinder {
    299300
    300301            @Override
    301             public void visit(IWay<?> w) {
     302            public void visit(IWay<INode> w) {
    302303                w.visitReferrers(innerVisitor);
    303304            }
    304305
     
    306307                super(e);
    307308            }
    308309
    309             private final PrimitiveVisitor innerVisitor = new AbstractFinder(e) {
     310            private final PrimitiveVisitor<INode, IWay<INode>, IRelation<?>> innerVisitor = new AbstractFinder(e) {
    310311                @Override
    311312                public void visit(IRelation<?> r) {
    312313                    if (r instanceof Relation && left.matches(e.withPrimitive(r))) {
     
    327328            private final String layer;
    328329            private Area area;
    329330            /** Will contain all way segments, grouped by cells */
    330             Map<Point2D, List<WaySegment>> cellSegments;
     331            Map<Point2D, List<WaySegment<Node, Way>>> cellSegments;
    331332
    332333            private CrossingFinder(Environment e) {
    333334                super(e);
     
    347348                return Geometry.getAreaEastNorth(p);
    348349            }
    349350
    350             private Map<List<Way>, List<WaySegment>> findCrossings(IPrimitive area,
    351                     Map<Point2D, List<WaySegment>> cellSegments) {
     351            private Map<List<Way>, List<WaySegment<Node, Way>>> findCrossings(IPrimitive area,
     352                    Map<Point2D, List<WaySegment<Node, Way>>> cellSegments) {
    352353                /** The detected crossing ways */
    353                 Map<List<Way>, List<WaySegment>> crossingWays = new HashMap<>(50);
     354                Map<List<Way>, List<WaySegment<Node, Way>>> crossingWays = new HashMap<>(50);
    354355                if (area instanceof Way) {
    355356                    CrossingWays.findIntersectingWay((Way) area, cellSegments, crossingWays, false);
    356357                } else if (area instanceof Relation && area.isMultipolygon()) {
     
    413414                    findCrossings(e.osm, cellSegments); // ignore self intersections etc. here
    414415                }
    415416                // need a copy
    416                 final Map<Point2D, List<WaySegment>> tmpCellSegments = new HashMap<>(cellSegments);
     417                final Map<Point2D, List<WaySegment<Node, Way>>> tmpCellSegments = new HashMap<>(cellSegments);
    417418                // calculate all crossings between e.osm and p
    418                 Map<List<Way>, List<WaySegment>> crossingWays = findCrossings(p, tmpCellSegments);
     419                Map<List<Way>, List<WaySegment<Node, Way>>> crossingWays = findCrossings(p, tmpCellSegments);
    419420                if (!crossingWays.isEmpty()) {
    420421                    addToChildren(e, p);
    421422                    if (e.crossingWaysMap == null) {
     
    469470            }
    470471
    471472            @Override
    472             public void visit(IWay<?> w) {
     473            public void visit(IWay<INode> w) {
    473474                if (left.matches(new Environment(w).withParent(e.osm))
    474475                        && w.getBBox().bounds(e.osm.getBBox())
    475476                        && !Geometry.filterInsidePolygon(Collections.singletonList(e.osm), w).isEmpty()) {
     
    601602                        }
    602603                    }
    603604                } else if (e.osm instanceof IRelation) {
    604                     List<? extends IRelationMember<?>> members = ((IRelation<?>) e.osm).getMembers();
     605                    List<? extends IRelationMember<?, ?, ?, ?>> members = ((IRelation<?>) e.osm).getMembers();
    605606                    for (int i = 0; i < members.size(); i++) {
    606607                        IPrimitive member = members.get(i).getMember();
    607608                        if (left.matches(e.withPrimitive(member))
  • src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java

     
    4141import org.openstreetmap.josm.data.UndoRedoHandler;
    4242import org.openstreetmap.josm.data.osm.DataSet;
    4343import org.openstreetmap.josm.data.osm.IPrimitive;
     44import org.openstreetmap.josm.data.osm.Node;
    4445import org.openstreetmap.josm.data.osm.OsmData;
    4546import org.openstreetmap.josm.data.osm.OsmDataManager;
    4647import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    4748import org.openstreetmap.josm.data.osm.Relation;
    4849import org.openstreetmap.josm.data.osm.RelationMember;
    4950import org.openstreetmap.josm.data.osm.Tag;
     51import org.openstreetmap.josm.data.osm.Way;
    5052import org.openstreetmap.josm.data.osm.search.SearchCompiler;
    5153import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
    5254import org.openstreetmap.josm.data.osm.search.SearchParseError;
     
    412414        }
    413415
    414416        if (!sel.isEmpty() && answer == DIALOG_ANSWER_APPLY) {
    415             Command cmd = createCommand(sel, getChangedTags());
     417            Command<?, ?, ?, ?> cmd = createCommand(sel, getChangedTags());
    416418            if (cmd != null) {
    417419                UndoRedoHandler.getInstance().add(cmd);
    418420            }
     
    547549     * @param changedTags The tags to change
    548550     * @return A command that changes the tags.
    549551     */
    550     public static Command createCommand(Collection<OsmPrimitive> sel, List<Tag> changedTags) {
    551         List<Command> cmds = new ArrayList<>();
     552    public static Command<?, ?, ?, ?> createCommand(Collection<OsmPrimitive> sel, List<Tag> changedTags) {
     553        List<Command<OsmPrimitive, Node, Way, Relation>> cmds = new ArrayList<>();
    552554        for (Tag tag: changedTags) {
    553555            ChangePropertyCommand cmd = new ChangePropertyCommand(sel, tag.getKey(), tag.getValue());
    554556            if (cmd.getObjectsNumber() > 0) {
  • src/org/openstreetmap/josm/tools/Geometry.java

     
    2626import org.openstreetmap.josm.data.coor.EastNorth;
    2727import org.openstreetmap.josm.data.coor.ILatLon;
    2828import org.openstreetmap.josm.data.osm.BBox;
    29 import org.openstreetmap.josm.data.osm.DataSet;
    3029import org.openstreetmap.josm.data.osm.INode;
    3130import org.openstreetmap.josm.data.osm.IPrimitive;
     31import org.openstreetmap.josm.data.osm.IRelation;
    3232import org.openstreetmap.josm.data.osm.IWay;
    3333import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
    3434import org.openstreetmap.josm.data.osm.MultipolygonBuilder.JoinedPolygon;
    3535import org.openstreetmap.josm.data.osm.Node;
    3636import org.openstreetmap.josm.data.osm.NodePositionComparator;
     37import org.openstreetmap.josm.data.osm.OsmData;
    3738import org.openstreetmap.josm.data.osm.OsmPrimitive;
    3839import org.openstreetmap.josm.data.osm.Relation;
    3940import org.openstreetmap.josm.data.osm.Way;
     
    9596     *              the ways.
    9697     * @return list of new nodes, if test is true the list might not contain all intersections
    9798     */
    98     public static Set<Node> addIntersections(List<Way> ways, boolean test, List<Command> cmds) {
     99    public static <O extends IPrimitive, N extends INode, W extends IWay<N>, R extends IRelation<?>> Set<N> addIntersections(List<W> ways, boolean test, List<Command<O, N, W, R>> cmds) {
    99100
    100101        int n = ways.size();
    101102        @SuppressWarnings("unchecked")
    102         List<Node>[] newNodes = new ArrayList[n];
     103        List<N>[] newNodes = new ArrayList[n];
    103104        BBox[] wayBounds = new BBox[n];
    104105        boolean[] changedWays = new boolean[n];
    105106
    106         Set<Node> intersectionNodes = new LinkedHashSet<>();
     107        Set<N> intersectionNodes = new LinkedHashSet<>();
    107108
    108109        //copy node arrays for local usage.
    109110        for (int pos = 0; pos < n; pos++) {
     
    112113            changedWays[pos] = false;
    113114        }
    114115
    115         DataSet dataset = ways.get(0).getDataSet();
     116        OsmData<O, N, W, R> dataset = ways.get(0).getDataSet();
    116117
    117118        //iterate over all way pairs and introduce the intersections
    118         Comparator<Node> coordsComparator = new NodePositionComparator();
     119        Comparator<N> coordsComparator = new NodePositionComparator<>();
    119120        for (int seg1Way = 0; seg1Way < n; seg1Way++) {
    120121            for (int seg2Way = seg1Way; seg2Way < n; seg2Way++) {
    121122
     
    124125                    continue;
    125126                }
    126127
    127                 List<Node> way1Nodes = newNodes[seg1Way];
    128                 List<Node> way2Nodes = newNodes[seg2Way];
     128                List<N> way1Nodes = newNodes[seg1Way];
     129                List<N> way2Nodes = newNodes[seg2Way];
    129130
    130131                //iterate over primary segmemt
    131132                for (int seg1Pos = 0; seg1Pos + 1 < way1Nodes.size(); seg1Pos++) {
     
    136137                    for (int seg2Pos = seg2Start; seg2Pos + 1 < way2Nodes.size(); seg2Pos++) {
    137138
    138139                        //need to get them again every time, because other segments may be changed
    139                         Node seg1Node1 = way1Nodes.get(seg1Pos);
    140                         Node seg1Node2 = way1Nodes.get(seg1Pos + 1);
    141                         Node seg2Node1 = way2Nodes.get(seg2Pos);
    142                         Node seg2Node2 = way2Nodes.get(seg2Pos + 1);
     140                        N seg1Node1 = way1Nodes.get(seg1Pos);
     141                        N seg1Node2 = way1Nodes.get(seg1Pos + 1);
     142                        N seg2Node1 = way2Nodes.get(seg2Pos);
     143                        N seg2Node2 = way2Nodes.get(seg2Pos + 1);
    143144
    144145                        int commonCount = 0;
    145146                        //test if we have common nodes to add.
     
    168169                                    seg2Node1.getEastNorth(), seg2Node2.getEastNorth());
    169170
    170171                            if (intersection != null) {
    171                                 Node newNode = new Node(ProjectionRegistry.getProjection().eastNorth2latlon(intersection));
    172                                 Node intNode = newNode;
     172                                N newNode = Utils.clone(seg1Node1);
     173                                newNode.removeAll(); // Make certain we don't keep any keys from the original node
     174                                newNode.setCoor(ProjectionRegistry.getProjection().eastNorth2latlon(intersection));
     175                                N intNode = newNode;
    173176                                boolean insertInSeg1 = false;
    174177                                boolean insertInSeg2 = false;
    175178                                //find if the intersection point is at end point of one of the segments, if so use that point
     
    218221                                intersectionNodes.add(intNode);
    219222
    220223                                if (intNode == newNode) {
    221                                     cmds.add(new AddCommand(dataset, intNode));
     224                                    cmds.add(new AddCommand<>(dataset, (O) intNode));
    222225                                }
    223226                            }
    224227                        } else if (test && !intersectionNodes.isEmpty())
     
    234237                continue;
    235238            }
    236239
    237             Way way = ways.get(pos);
    238             Way newWay = new Way(way);
     240            W way = ways.get(pos);
     241            W newWay = Utils.clone(way);
    239242            newWay.setNodes(newNodes[pos]);
    240243
    241             cmds.add(new ChangeCommand(dataset, way, newWay));
     244            cmds.add(new ChangeCommand<>(dataset, (O) way, (O) newWay));
    242245        }
    243246
    244247        return intersectionNodes;
     
    15401543     * May return {@link Double#NaN}.
    15411544     * @since 15035
    15421545     */
    1543     public static double getDistanceSegmentSegment(WaySegment ws1, WaySegment ws2) {
     1546    public static <N extends INode, W extends IWay<N>> double getDistanceSegmentSegment(WaySegment<N, W> ws1, WaySegment<N, W> ws2) {
    15441547        return getDistanceSegmentSegment(ws1.getFirstNode(), ws1.getSecondNode(), ws2.getFirstNode(), ws2.getSecondNode());
    15451548    }
    15461549
     
    15551558     * May return {@link Double#NaN}.
    15561559     * @since 15035
    15571560     */
    1558     public static double getDistanceSegmentSegment(Node ws1Node1, Node ws1Node2, Node ws2Node1, Node ws2Node2) {
     1561    public static double getDistanceSegmentSegment(INode ws1Node1, INode ws1Node2, INode ws2Node1, INode ws2Node2) {
    15591562        EastNorth enWs1Node1 = ws1Node1.getEastNorth();
    15601563        EastNorth enWs1Node2 = ws1Node2.getEastNorth();
    15611564        EastNorth enWs2Node1 = ws2Node1.getEastNorth();
  • src/org/openstreetmap/josm/tools/Utils.java

     
    1515import java.io.IOException;
    1616import java.io.InputStream;
    1717import java.io.UnsupportedEncodingException;
     18import java.lang.reflect.InvocationTargetException;
    1819import java.net.MalformedURLException;
    1920import java.net.URI;
    2021import java.net.URISyntaxException;
     
    6869import javax.script.ScriptEngine;
    6970import javax.script.ScriptEngineManager;
    7071
    71 import com.kitfox.svg.xml.XMLParseUtil;
    7272import org.openstreetmap.josm.spi.preferences.Config;
    7373
     74import com.kitfox.svg.xml.XMLParseUtil;
     75
    7476/**
    7577 * Basic utils, that can be useful in different parts of the program.
    7678 */
     
    19451947        // remove extra whitespaces
    19461948        return rawString.trim();
    19471949    }
     1950
     1951    /**
     1952     * Clone an object that has a cloning constructor
     1953     *
     1954     * @param <T> The object class to clone
     1955     * @param object The object that is cloned
     1956     * @return The cloned object, or {@code null}
     1957     */
     1958    @SuppressWarnings("unchecked")
     1959    public static <T> T clone(T object) {
     1960        try {
     1961            Object obj = object.getClass().getConstructor(object.getClass()).newInstance(object);
     1962            if (object.getClass().isAssignableFrom(obj.getClass())) {
     1963                return (T) obj;
     1964            } else {
     1965                return null;
     1966            }
     1967        } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
     1968            Logging.error(e);
     1969            return null;
     1970        }
     1971    }
    19481972}
  • test/unit/org/openstreetmap/josm/TestUtils.java

     
    389389     * @param ds data set
    390390