001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.util.Arrays;
005import java.util.Objects;
006import java.util.Optional;
007
008import org.openstreetmap.josm.tools.CheckParameterUtil;
009
010/**
011 * A linkage class that can be used by an relation to keep a list of
012 * members. Since membership may be qualified by a "role", a simple
013 * list is not sufficient.
014 *
015 */
016public class RelationMember implements PrimitiveId {
017
018    /**
019     *
020     */
021    private final String role;
022
023    /**
024     *
025     */
026    private final OsmPrimitive member;
027
028    /**
029     * Returns the role of this relation member.
030     * @return Role name or "". Never returns null
031     * @since 1930
032     */
033    public String getRole() {
034        return role;
035    }
036
037    /**
038     * Determines if this relation member has a role.
039     * @return True if role is set
040     * @since 1930
041     */
042    public boolean hasRole() {
043        return !"".equals(role);
044    }
045
046    /**
047     * Determines if this relation member's role is in the given list.
048     * @param roles The roles to look after
049     * @return True if role is in the given list
050     * @since 6305
051     */
052    public boolean hasRole(String... roles) {
053        return Arrays.asList(roles).contains(role);
054    }
055
056    /**
057     * Determines if this relation member is a relation.
058     * @return True if member is relation
059     * @since 1937
060     */
061    public boolean isRelation() {
062        return member instanceof Relation;
063    }
064
065    /**
066     * Determines if this relation member is a way.
067     * @return True if member is way
068     * @since 1937
069     */
070    public boolean isWay() {
071        return member instanceof Way;
072    }
073
074    /**
075     *
076     * @return type of member for icon display
077     * @since 3844
078     */
079    public OsmPrimitiveType getDisplayType() {
080        return member.getDisplayType();
081    }
082
083    /**
084     * Determines if this relation member is a node.
085     * @return True if member is node
086     * @since 1937
087     */
088    public boolean isNode() {
089        return member instanceof Node;
090    }
091
092    /**
093     * Returns the relation member as a relation.
094     * @return Member as relation
095     * @since 1937
096     */
097    public Relation getRelation() {
098        return (Relation) member;
099    }
100
101    /**
102     * Returns the relation member as a way.
103     * @return Member as way
104     * @since 1937
105     */
106    public Way getWay() {
107        return (Way) member;
108    }
109
110    /**
111     * Returns the relation member as a node.
112     * @return Member as node
113     * @since 1937
114     */
115    public Node getNode() {
116        return (Node) member;
117    }
118
119    /**
120     * Returns the relation member.
121     * @return Member. Returned value is never null.
122     * @since 1937
123     */
124    public OsmPrimitive getMember() {
125        return member;
126    }
127
128    /**
129     * Constructs a new {@code RelationMember}.
130     * @param role Can be null, in this case it's save as ""
131     * @param member Cannot be null
132     * @throws IllegalArgumentException if member is <code>null</code>
133     */
134    public RelationMember(String role, OsmPrimitive member) {
135        CheckParameterUtil.ensureParameterNotNull(member, "member");
136        this.role = Optional.ofNullable(role).orElse("");
137        this.member = member;
138    }
139
140    /**
141     * Copy constructor.
142     * This constructor is left only for backwards compatibility. Copying RelationMember doesn't make sense
143     * because it's immutable
144     * @param other relation member to be copied.
145     */
146    public RelationMember(RelationMember other) {
147        this(other.role, other.member);
148    }
149
150    @Override
151    public String toString() {
152        return '"' + role + "\"=" + member;
153    }
154
155    /**
156     * Replies true, if this relation member refers to the primitive
157     *
158     * @param primitive  the primitive to check
159     * @return true, if this relation member refers to the primitive
160     */
161    public boolean refersTo(OsmPrimitive primitive) {
162        return member == primitive;
163    }
164
165    @Override
166    public int hashCode() {
167        return Objects.hash(role, member);
168    }
169
170    @Override
171    public boolean equals(Object obj) {
172        if (this == obj) return true;
173        if (obj == null || getClass() != obj.getClass()) return false;
174        RelationMember that = (RelationMember) obj;
175        return Objects.equals(role, that.role) &&
176               Objects.equals(member, that.member);
177    }
178
179    /**
180     * PrimitiveId implementation. Returns the same value as getMember().getType()
181     */
182    @Override
183    public OsmPrimitiveType getType() {
184        return member.getType();
185    }
186
187    /**
188     * PrimitiveId implementation. Returns the same value as getMemberType().getUniqueId()
189     */
190    @Override
191    public long getUniqueId() {
192        return member.getUniqueId();
193    }
194
195    @Override
196    public boolean isNew() {
197        return member.isNew();
198    }
199}