001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm.history; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.ArrayList; 007import java.util.Collections; 008import java.util.Date; 009import java.util.List; 010import java.util.Objects; 011 012import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 013import org.openstreetmap.josm.data.osm.User; 014import org.openstreetmap.josm.data.osm.Way; 015import org.openstreetmap.josm.data.osm.WayData; 016import org.openstreetmap.josm.tools.CheckParameterUtil; 017 018/** 019 * Represents an immutable OSM way in the context of a historical view on OSM data. 020 * @since 1670 021 */ 022public class HistoryWay extends HistoryOsmPrimitive { 023 024 private final List<Long> nodeIds = new ArrayList<>(); 025 026 /** 027 * Constructs a new {@code HistoryWay}. 028 * 029 * @param id the id (> 0 required) 030 * @param version the version (> 0 required) 031 * @param visible whether the node is still visible 032 * @param user the user (!= null required) 033 * @param changesetId the changeset id (> 0 required if {@code checkHistoricParams} is true) 034 * @param timestamp the timestamp (!= null required if {@code checkHistoricParams} is true) 035 * @throws IllegalArgumentException if preconditions are violated 036 */ 037 public HistoryWay(long id, long version, boolean visible, User user, long changesetId, Date timestamp) { 038 super(id, version, visible, user, changesetId, timestamp); 039 } 040 041 /** 042 * Constructs a new {@code HistoryWay} with a configurable checking of historic parameters. 043 * This is needed to build virtual HistoryWays for modified ways, which do not have a timestamp and a changeset id. 044 * 045 * @param id the id (> 0 required) 046 * @param version the version (> 0 required) 047 * @param visible whether the node is still visible 048 * @param user the user (!= null required) 049 * @param changesetId the changeset id (> 0 required if {@code checkHistoricParams} is true) 050 * @param timestamp the timestamp (!= null required if {@code checkHistoricParams} is true) 051 * @param checkHistoricParams if true, checks values of {@code changesetId} and {@code timestamp} 052 * @throws IllegalArgumentException if preconditions are violated 053 * @since 5440 054 */ 055 public HistoryWay(long id, long version, boolean visible, User user, long changesetId, Date timestamp, boolean checkHistoricParams) { 056 super(id, version, visible, user, changesetId, timestamp, checkHistoricParams); 057 } 058 059 /** 060 * Constructs a new {@code HistoryWay} with a given list of node ids. 061 * 062 * @param id the id (> 0 required) 063 * @param version the version (> 0 required) 064 * @param visible whether the node is still visible 065 * @param user the user (!= null required) 066 * @param changesetId the changeset id (> 0 required if {@code checkHistoricParams} is true) 067 * @param timestamp the timestamp (!= null required if {@code checkHistoricParams} is true) 068 * @param nodeIdList the node ids (!= null required) 069 * @throws IllegalArgumentException if preconditions are violated 070 */ 071 public HistoryWay(long id, long version, boolean visible, User user, long changesetId, Date timestamp, List<Long> nodeIdList) { 072 this(id, version, visible, user, changesetId, timestamp); 073 CheckParameterUtil.ensureParameterNotNull(nodeIdList, "nodeIdList"); 074 this.nodeIds.addAll(nodeIdList); 075 } 076 077 /** 078 * Constructs a new {@code HistoryWay} from an existing {@link Way}. 079 * @param w the way 080 */ 081 public HistoryWay(Way w) { 082 super(w); 083 } 084 085 /** 086 * replies the number of nodes in this way 087 * @return the number of nodes 088 */ 089 public int getNumNodes() { 090 return nodeIds.size(); 091 } 092 093 /** 094 * replies the idx-th node id in the list of node ids of this way 095 * 096 * @param idx the index 097 * @return the idx-th node id 098 * @throws IndexOutOfBoundsException if idx < 0 || idx >= {#see {@link #getNumNodes()} 099 */ 100 public long getNodeId(int idx) { 101 if (idx < 0 || idx >= nodeIds.size()) 102 throw new IndexOutOfBoundsException(tr("Parameter {0} not in range 0..{1}. Got ''{2}''.", "idx", nodeIds.size(), idx)); 103 return nodeIds.get(idx); 104 } 105 106 /** 107 * replies an immutable list of the ways node ids 108 * 109 * @return the ways node ids 110 */ 111 public List<Long> getNodes() { 112 return Collections.unmodifiableList(nodeIds); 113 } 114 115 /** 116 * replies the ways type, i.e. {@link OsmPrimitiveType#WAY} 117 * 118 * @return the ways type 119 */ 120 @Override 121 public OsmPrimitiveType getType() { 122 return OsmPrimitiveType.WAY; 123 } 124 125 /** 126 * adds a node id to the list nodes of this way 127 * 128 * @param ref the node id to add 129 */ 130 public void addNode(long ref) { 131 nodeIds.add(ref); 132 } 133 134 /** 135 * Replies true if this way is closed. 136 * 137 * @return true if this way is closed. 138 */ 139 public boolean isClosed() { 140 return getNumNodes() >= 3 && Objects.equals(nodeIds.get(0), nodeIds.get(nodeIds.size()-1)); 141 } 142 143 @Override 144 public String getDisplayName(HistoryNameFormatter formatter) { 145 return formatter.format(this); 146 } 147 148 /** 149 * Fills the way attributes with values from this history. 150 * @param data way data to fill 151 * @return filled way data 152 * @since 11878 153 */ 154 public WayData fillPrimitiveData(WayData data) { 155 super.fillPrimitiveCommonData(data); 156 data.setNodeIds(nodeIds); 157 return data; 158 } 159}