001 // License: GPL. Copyright 2007 by Martijn van Oosterhout and others 002 package org.openstreetmap.josm.data.osm; 003 004 import java.util.Collection; 005 import java.util.Date; 006 import java.util.HashMap; 007 import java.util.Map; 008 009 import org.openstreetmap.josm.data.Bounds; 010 import org.openstreetmap.josm.data.coor.LatLon; 011 import org.openstreetmap.josm.data.osm.visitor.Visitor; 012 013 /** 014 * Represents a single changeset in JOSM. For now its only used during 015 * upload but in the future we may do more. 016 * 017 */ 018 public final class Changeset implements Tagged { 019 020 /** The maximum changeset comment text length allowed by API 0.6 **/ 021 public static final int MAX_COMMENT_LENGTH = 255; 022 023 /** the changeset id */ 024 private int id; 025 /** the user who owns the changeset */ 026 private User user; 027 /** date this changeset was created at */ 028 private Date createdAt; 029 /** the date this changeset was closed at*/ 030 private Date closedAt; 031 /** indicates whether this changeset is still open or not */ 032 private boolean open; 033 /** the min. coordinates of the bounding box of this changeset */ 034 private LatLon min; 035 /** the max. coordinates of the bounding box of this changeset */ 036 private LatLon max; 037 /** the map of tags */ 038 private Map<String,String> tags; 039 /** indicates whether this changeset is incomplete. For an 040 * incomplete changeset we only know its id 041 */ 042 private boolean incomplete; 043 /** the changeset content */ 044 private ChangesetDataSet content = null; 045 046 /** 047 * Creates a new changeset with id 0. 048 */ 049 public Changeset() { 050 this.id = 0; 051 this.tags = new HashMap<String, String>(); 052 } 053 054 /** 055 * Creates a changeset with id <code>id</code>. If id > 0, sets incomplete to true. 056 * 057 * @param id the id 058 */ 059 public Changeset(int id) { 060 this.id = id; 061 this.incomplete = id > 0; 062 this.tags = new HashMap<String, String>(); 063 } 064 065 /** 066 * Creates a clone of <code>other</code> 067 * 068 * @param other the other changeset. If null, creates a new changeset with id 0. 069 */ 070 public Changeset(Changeset other) { 071 if (other == null) { 072 this.id = 0; 073 this.tags = new HashMap<String, String>(); 074 } else if (other.isIncomplete()) { 075 setId(other.getId()); 076 this.incomplete = true; 077 this.tags = new HashMap<String, String>(); 078 } else { 079 this.id = other.id; 080 mergeFrom(other); 081 this.incomplete = false; 082 } 083 } 084 085 public void visit(Visitor v) { 086 v.visit(this); 087 } 088 089 public int compareTo(Changeset other) { 090 return Integer.valueOf(getId()).compareTo(other.getId()); 091 } 092 093 public String getName() { 094 // no translation 095 return "changeset " + getId(); 096 } 097 098 public String getDisplayName(NameFormatter formatter) { 099 return formatter.format(this); 100 } 101 102 public int getId() { 103 return id; 104 } 105 106 public void setId(int id) { 107 this.id = id; 108 } 109 110 public User getUser() { 111 return user; 112 } 113 114 public void setUser(User user) { 115 this.user = user; 116 } 117 118 public Date getCreatedAt() { 119 return createdAt; 120 } 121 122 public void setCreatedAt(Date createdAt) { 123 this.createdAt = createdAt; 124 } 125 126 public Date getClosedAt() { 127 return closedAt; 128 } 129 130 public void setClosedAt(Date closedAt) { 131 this.closedAt = closedAt; 132 } 133 134 public boolean isOpen() { 135 return open; 136 } 137 138 public void setOpen(boolean open) { 139 this.open = open; 140 } 141 142 public LatLon getMin() { 143 return min; 144 } 145 146 public void setMin(LatLon min) { 147 this.min = min; 148 } 149 150 public LatLon getMax() { 151 return max; 152 } 153 154 public Bounds getBounds() { 155 if (min != null && max != null) 156 return new Bounds(min,max); 157 return null; 158 } 159 160 public void setMax(LatLon max) { 161 this.max = max; 162 } 163 164 public Map<String, String> getKeys() { 165 return tags; 166 } 167 168 public void setKeys(Map<String, String> keys) { 169 this.tags = keys; 170 } 171 172 public boolean isIncomplete() { 173 return incomplete; 174 } 175 176 public void setIncomplete(boolean incomplete) { 177 this.incomplete = incomplete; 178 } 179 180 public void put(String key, String value) { 181 this.tags.put(key, value); 182 } 183 184 public String get(String key) { 185 return this.tags.get(key); 186 } 187 188 public void remove(String key) { 189 this.tags.remove(key); 190 } 191 192 public void removeAll() { 193 this.tags.clear(); 194 } 195 196 public boolean hasEqualSemanticAttributes(Changeset other) { 197 if (other == null) 198 return false; 199 if (closedAt == null) { 200 if (other.closedAt != null) 201 return false; 202 } else if (!closedAt.equals(other.closedAt)) 203 return false; 204 if (createdAt == null) { 205 if (other.createdAt != null) 206 return false; 207 } else if (!createdAt.equals(other.createdAt)) 208 return false; 209 if (id != other.id) 210 return false; 211 if (max == null) { 212 if (other.max != null) 213 return false; 214 } else if (!max.equals(other.max)) 215 return false; 216 if (min == null) { 217 if (other.min != null) 218 return false; 219 } else if (!min.equals(other.min)) 220 return false; 221 if (open != other.open) 222 return false; 223 if (tags == null) { 224 if (other.tags != null) 225 return false; 226 } else if (!tags.equals(other.tags)) 227 return false; 228 if (user == null) { 229 if (other.user != null) 230 return false; 231 } else if (!user.equals(other.user)) 232 return false; 233 return true; 234 } 235 236 @Override 237 public int hashCode() { 238 if (id > 0) 239 return id; 240 else 241 return super.hashCode(); 242 } 243 244 @Override 245 public boolean equals(Object obj) { 246 if (this == obj) 247 return true; 248 if (obj == null) 249 return false; 250 if (getClass() != obj.getClass()) 251 return false; 252 Changeset other = (Changeset) obj; 253 if (this.id > 0 && other.id == this.id) 254 return true; 255 return this == obj; 256 } 257 258 public boolean hasKeys() { 259 return !tags.keySet().isEmpty(); 260 } 261 262 public Collection<String> keySet() { 263 return tags.keySet(); 264 } 265 266 public boolean isNew() { 267 return id <= 0; 268 } 269 270 public void mergeFrom(Changeset other) { 271 if (other == null) 272 return; 273 if (id != other.id) 274 return; 275 this.user = other.user; 276 this.createdAt = other.createdAt; 277 this.closedAt = other.closedAt; 278 this.open = other.open; 279 this.min = other.min; 280 this.max = other.max; 281 this.tags = new HashMap<String, String>(other.tags); 282 this.incomplete = other.incomplete; 283 284 // FIXME: merging of content required? 285 this.content = other.content; 286 } 287 288 public boolean hasContent() { 289 return content != null; 290 } 291 292 public ChangesetDataSet getContent() { 293 return content; 294 } 295 296 public void setContent(ChangesetDataSet content) { 297 this.content = content; 298 } 299 }