001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.relation.sort;
003
004import static org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction.NONE;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007/**
008 * A class used by the {@link RelationSorter} to store if two ways are already connected
009 */
010public class WayConnectionType {
011
012    /** True, if the corresponding primitive is not a way or the way is incomplete */
013    private final boolean invalid;
014
015    /** True, if linked to the previous member.  */
016    public boolean linkPrev;
017    /** True, if linked to the next member.  */
018    public boolean linkNext;
019
020    /**
021     * direction is FORWARD if the first node of this way is connected to the previous way
022     * and / or the last node of this way is connected to the next way.
023     * direction is BACKWARD if it is the other way around.
024     * direction has a ONEWAY value, if it is tagged as such and it is connected
025     * to the previous / next member.
026     * ONEWAY_FORWARD == the first node of the oneway is the last node of the previous way
027     * ONEWAY_BACKWARD == the last node of the oneway is the last node of the previous way
028     * direction has a ROUNDABOUT value, if it is tagged as such and it is somehow
029     * connected to the previous / next member.
030     * If there is no connection to the previous or next member, then
031     * direction has the value NONE.
032     */
033    public Direction direction;
034
035    public enum Direction {
036        FORWARD, BACKWARD, ROUNDABOUT_LEFT, ROUNDABOUT_RIGHT, NONE;
037
038        /**
039         * Determines if the direction denotes a roundabout.
040         * @return {@code true} if the direction denotes a roundabout
041         */
042        public boolean isRoundabout() {
043            return this == ROUNDABOUT_RIGHT || this == ROUNDABOUT_LEFT;
044        }
045    }
046
047    /** True, if the element is part of a closed loop of ways. */
048    public boolean isLoop;
049
050    /** True, if all oneway features are ignored */
051    public boolean ignoreOneway;
052
053    public boolean isOnewayLoopForwardPart;
054    public boolean isOnewayLoopBackwardPart;
055    public boolean isOnewayHead;
056    public boolean isOnewayTail;
057
058    /** False, if the way is oneway and it doesn't follow the flow of the previous member */
059    public boolean onewayFollowsPrevious = true;
060    /** True, if the way is oneway and it doesn't follow the flow of the next member */
061    public boolean onewayFollowsNext = true;
062
063    /**
064     * Constructs a valid instance.
065     * @param linkPrev {@code true} if linked to the previous member
066     * @param linkNext {@code true} if linked to the next member
067     * @param direction the direction type
068     */
069    public WayConnectionType(boolean linkPrev, boolean linkNext, Direction direction) {
070        this.linkPrev = linkPrev;
071        this.linkNext = linkNext;
072        this.isLoop = false;
073        this.direction = direction;
074        invalid = false;
075    }
076
077    /**
078     * Constructs a valid or invalid instance.
079     * @param invalid {@code true} if the instance is invalid (i.e does not concern a complete way)
080     */
081    public WayConnectionType(boolean invalid) {
082        this.linkPrev = false;
083        this.linkNext = false;
084        this.isLoop = false;
085        this.direction = NONE;
086        this.invalid = invalid;
087    }
088
089    /** construct invalid instance */
090    public WayConnectionType() {
091        this(true);
092    }
093
094    /**
095     * Determines if the connection type is valid (i.e. it concerns a complete way).
096     * @return {@code true} if the connection type is valid (i.e. it concerns a complete way)
097     */
098    public boolean isValid() {
099        return !invalid;
100    }
101
102    @Override
103    public String toString() {
104        return "[P "+linkPrev+" ;N "+linkNext+" ;D "+direction+" ;L "+isLoop+
105                " ;FP " + isOnewayLoopForwardPart+";BP " + isOnewayLoopBackwardPart+
106                ";OH " + isOnewayHead+";OT " + isOnewayTail+']';
107    }
108
109    /**
110     * Returns the tooltip to display when hovering over the relation member.
111     * @return The tooltip, never null.
112     * @since 10248
113     */
114    public String getTooltip() {
115        boolean onewayGood = onewayFollowsPrevious && onewayFollowsNext;
116        if (!isValid())
117            return "";
118        else if (linkPrev && linkNext && onewayGood)
119            return tr("way is connected");
120        else if (linkPrev && linkNext && !onewayGood)
121            return tr("way is connected but has a wrong oneway direction");
122        else if (linkPrev && onewayGood)
123            return tr("way is connected to previous relation member");
124        else if (linkPrev && !onewayGood)
125            return tr("way is connected to previous relation member but has a wrong oneway direction");
126        else if (linkNext && onewayGood)
127            return tr("way is connected to next relation member");
128        else if (linkNext && !onewayGood)
129            return tr("way is connected to next relation member but has a wrong oneway direction");
130        else
131            return tr("way is not connected to previous or next relation member");
132    }
133}