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