001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.util.List;
005
006/**
007 * IWay captures the common functions of {@link Way} and {@link WayData}.
008 * @param <N> type of OSM node
009 * @since 4098
010 */
011public interface IWay<N extends INode> extends IPrimitive {
012
013    /**
014     * Replies the number of nodes in this way.
015     *
016     * @return the number of nodes in this way.
017     */
018    int getNodesCount();
019
020    /**
021     * Determines if this way is empty, i.e. it has no nodes.
022     * @return {@code true} if this way is empty, i.e. it has no nodes
023     * @since 16119
024     */
025    default boolean isEmpty() {
026        return getNodesCount() == 0;
027    }
028
029    /**
030     * Replies the real number of nodes in this way (full number of nodes minus one if this way is closed)
031     *
032     * @return the real number of nodes in this way.
033     *
034     * @see #getNodesCount()
035     * @see #isClosed()
036     * @since 5847
037     * @since 13564 (IWay)
038     */
039    default int getRealNodesCount() {
040        int count = getNodesCount();
041        return isClosed() ? count-1 : count;
042    }
043
044    /**
045     * Replies the node at position <code>index</code>.
046     *
047     * @param index the position
048     * @return  the node at position <code>index</code>
049     * @throws ArrayIndexOutOfBoundsException if <code>index</code> &lt; 0
050     * or <code>index</code> &gt;= {@link #getNodesCount()}
051     * @since 1862
052     * @since 13717 (IWay)
053     */
054    N getNode(int index);
055
056    /**
057     * Returns the list of nodes in this way.
058     * @return the list of nodes in this way
059     * @since 1862
060     * @since 13717 (IWay)
061     */
062    List<N> getNodes();
063
064    /**
065     * Returns the list of node ids in this way.
066     * @return the list of node ids in this way
067     * @since 13717
068     */
069    List<Long> getNodeIds();
070
071    /**
072     * Returns id of the node at given index.
073     * @param idx node index
074     * @return id of the node at given index
075     */
076    long getNodeId(int idx);
077
078    /**
079     * Set new list of nodes to way. This method is preferred to multiple calls to addNode/removeNode
080     * and similar methods because nodes are internally saved as array which means lower memory overhead
081     * but also slower modifying operations.
082     * @param nodes New way nodes. Can be null, in that case all way nodes are removed
083     */
084    void setNodes(List<N> nodes);
085
086    /**
087     * Determines if this way is closed.
088     * @return {@code true} if this way is closed, {@code false} otherwise
089     */
090    boolean isClosed();
091
092    @Override
093    default int compareTo(IPrimitive o) {
094        if (o instanceof IRelation)
095            return 1;
096        return o instanceof IWay ? Long.compare(getUniqueId(), o.getUniqueId()) : -1;
097    }
098
099    @Override
100    default String getDisplayName(NameFormatter formatter) {
101        return formatter.format(this);
102    }
103
104    /**
105     * Returns the first node of this way.
106     * The result equals {@link #getNode getNode}{@code (0)}.
107     * @return the first node of this way
108     * @since 13922
109     */
110    N firstNode();
111
112    /**
113     * Returns the last node of this way.
114     * The result equals <code>{@link #getNode getNode}({@link #getNodesCount getNodesCount} - 1)</code>.
115     * @return the last node of this way
116     * @since 13922
117     */
118    N lastNode();
119
120    /**
121     * Replies true if the given node is the first or the last one of this way, false otherwise.
122     * @param n The node to test
123     * @return true if the {@code n} is the first or the last node, false otherwise.
124     * @since 13922
125     */
126    boolean isFirstLastNode(INode n);
127
128    /**
129     * Replies true if the given node is an inner node of this way, false otherwise.
130     * @param n The node to test
131     * @return true if the {@code n} is an inner node, false otherwise.
132     * @since 13922
133     */
134    boolean isInnerNode(INode n);
135
136    /**
137     * Replies true if this way has incomplete nodes, false otherwise.
138     * @return true if this way has incomplete nodes, false otherwise.
139     * @since 18019
140     */
141    default boolean hasIncompleteNodes() {
142        return false;
143    }
144}