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