001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.util.Collection; 005import java.util.HashSet; 006import java.util.List; 007import java.util.Set; 008 009import org.openstreetmap.josm.tools.Utils; 010 011/** 012 * IRelation captures the common functions of {@link Relation} and {@link RelationData}. 013 * @param <M> Type of OSM relation member 014 * @since 4098 015 */ 016public interface IRelation<M extends IRelationMember<?>> extends IPrimitive { 017 018 /** 019 * Returns the number of members. 020 * @return number of members 021 */ 022 int getMembersCount(); 023 024 /** 025 * Returns the relation member at the specified index. 026 * @param index the index of the relation member 027 * @return relation member at the specified index 028 * @since 13766 (IRelation) 029 */ 030 M getMember(int index); 031 032 /** 033 * Returns members of the relation. 034 * @return Members of the relation. Changes made in returned list are not mapped 035 * back to the primitive, use {@link #setMembers} to modify the members 036 * @since 1925 037 * @since 13766 (IRelation) 038 */ 039 List<M> getMembers(); 040 041 /** 042 * Sets members of the relation. 043 * @param members Can be null, in that case all members are removed 044 */ 045 void setMembers(List<M> members); 046 047 /** 048 * Returns id of the member at given index. 049 * @param idx member index 050 * @return id of the member at given index 051 */ 052 long getMemberId(int idx); 053 054 /** 055 * Returns role of the member at given index. 056 * @param idx member index 057 * @return role of the member at given index 058 */ 059 String getRole(int idx); 060 061 /** 062 * Returns type of the member at given index. 063 * @param idx member index 064 * @return type of the member at given index 065 */ 066 OsmPrimitiveType getMemberType(int idx); 067 068 /** 069 * Determines if at least one child primitive is incomplete. 070 * 071 * @return true if at least one child primitive is incomplete 072 * @since 13564 073 */ 074 default boolean hasIncompleteMembers() { 075 return false; 076 } 077 078 @Override 079 default int compareTo(IPrimitive o) { 080 return o instanceof IRelation ? Long.compare(getUniqueId(), o.getUniqueId()) : -1; 081 } 082 083 @Override 084 default String getDisplayName(NameFormatter formatter) { 085 return formatter.format(this); 086 } 087 088 /** 089 * Determines if this relation is a boundary. 090 * @return {@code true} if a boundary relation 091 */ 092 default boolean isBoundary() { 093 return "boundary".equals(get("type")); 094 } 095 096 @Override 097 default boolean isMultipolygon() { 098 return "multipolygon".equals(get("type")) || isBoundary(); 099 } 100 101 /** 102 * Returns an unmodifiable list of the {@link OsmPrimitive}s referred to by at least one member of this relation. 103 * @return an unmodifiable list of the primitives 104 * @since 13957 105 */ 106 default List<? extends IPrimitive> getMemberPrimitivesList() { 107 return Utils.transform(getMembers(), IRelationMember::getMember); 108 } 109 110 /** 111 * Replies a collection with the incomplete children this relation refers to. 112 * 113 * @return the incomplete children. Empty collection if no children are incomplete. 114 * @since 13957 115 */ 116 default Collection<? extends IPrimitive> getIncompleteMembers() { 117 Set<IPrimitive> ret = new HashSet<>(); 118 for (M rm : getMembers()) { 119 if (!rm.getMember().isIncomplete()) { 120 continue; 121 } 122 ret.add(rm.getMember()); 123 } 124 return ret; 125 } 126}