001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.time.Instant; 005import java.util.Date; 006import java.util.List; 007import java.util.Map; 008 009import org.openstreetmap.josm.data.IQuadBucketType; 010import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor; 011import org.openstreetmap.josm.tools.LanguageInfo; 012 013/** 014 * IPrimitive captures the common functions of {@link OsmPrimitive} and {@link PrimitiveData}. 015 * @since 4098 016 */ 017public interface IPrimitive extends IQuadBucketType, Tagged, PrimitiveId, Stylable, Comparable<IPrimitive> { 018 019 /** 020 * Replies <code>true</code> if the object has been modified since it was loaded from 021 * the server. In this case, on next upload, this object will be updated. 022 * 023 * Deleted objects are deleted from the server. If the objects are added (id=0), 024 * the modified is ignored and the object is added to the server. 025 * 026 * @return <code>true</code> if the object has been modified since it was loaded from 027 * the server 028 */ 029 boolean isModified(); 030 031 /** 032 * Marks this primitive as being modified. 033 * 034 * @param modified true, if this primitive is to be modified 035 */ 036 void setModified(boolean modified); 037 038 /** 039 * Checks if object is known to the server. 040 * Replies true if this primitive is either unknown to the server (i.e. its id 041 * is 0) or it is known to the server and it hasn't be deleted on the server. 042 * Replies false, if this primitive is known on the server and has been deleted 043 * on the server. 044 * 045 * @return <code>true</code>, if the object is visible on server. 046 * @see #setVisible(boolean) 047 */ 048 boolean isVisible(); 049 050 /** 051 * Sets whether this primitive is visible, i.e. whether it is known on the server 052 * and not deleted on the server. 053 * @param visible {@code true} if this primitive is visible 054 * 055 * @throws IllegalStateException if visible is set to false on an primitive with id==0 056 * @see #isVisible() 057 */ 058 void setVisible(boolean visible); 059 060 /** 061 * Replies <code>true</code>, if the object has been deleted. 062 * 063 * @return <code>true</code>, if the object has been deleted. 064 * @see #setDeleted(boolean) 065 */ 066 boolean isDeleted(); 067 068 /** 069 * Sets whether this primitive is deleted or not. 070 * 071 * Also marks this primitive as modified if deleted is true. 072 * 073 * @param deleted true, if this primitive is deleted; false, otherwise 074 */ 075 void setDeleted(boolean deleted); 076 077 /** 078 * Determines if this primitive is incomplete. 079 * @return {@code true} if this primitive is incomplete, {@code false} otherwise 080 */ 081 boolean isIncomplete(); 082 083 /** 084 * Replies <code>true</code> if the object has been deleted on the server and was undeleted by the user. 085 * @return <code>true</code> if the object has been undeleted 086 */ 087 boolean isUndeleted(); 088 089 /** 090 * Replies <code>true</code>, if the object is usable 091 * (i.e. complete and not deleted). 092 * 093 * @return <code>true</code>, if the object is usable. 094 * @see #setDeleted(boolean) 095 */ 096 boolean isUsable(); 097 098 /** 099 * Determines if this primitive is new or undeleted. 100 * @return True if primitive is new or undeleted 101 * @see #isNew() 102 * @see #isUndeleted() 103 */ 104 boolean isNewOrUndeleted(); 105 106 /** 107 * Replies true, if this primitive is disabled. (E.g. a filter applies) 108 * @return {@code true} if this object has the "disabled" flag enabled 109 * @since 13662 110 */ 111 default boolean isDisabled() { 112 return false; 113 } 114 115 /** 116 * Replies true, if this primitive is disabled and marked as completely hidden on the map. 117 * @return {@code true} if this object has both the "disabled" and "hide if disabled" flags enabled 118 * @since 13662 119 */ 120 default boolean isDisabledAndHidden() { 121 return false; 122 } 123 124 /** 125 * Replies true, if this primitive is preserved from filtering. 126 * @return {@code true} if this object has the "preserved" flag enabled 127 * @since 13764 128 */ 129 default boolean isPreserved() { 130 return false; 131 } 132 133 /** 134 * Determines if this object is selectable. 135 * <p> 136 * A primitive can be selected if all conditions are met: 137 * <ul> 138 * <li>it is drawable 139 * <li>it is not disabled (greyed out) by a filter. 140 * </ul> 141 * @return {@code true} if this object is selectable 142 * @since 13664 143 */ 144 default boolean isSelectable() { 145 return true; 146 } 147 148 /** 149 * Determines if this object is drawable. 150 * <p> 151 * A primitive is drawable if all conditions are met: 152 * <ul> 153 * <li>type and id is known 154 * <li>tags are known 155 * <li>it is not deleted 156 * <li>it is not hidden by a filter 157 * <li>for nodes: lat/lon are known 158 * <li>for ways: all nodes are known and complete 159 * <li>for relations: all members are known and complete 160 * </ul> 161 * @return {@code true} if this object is drawable 162 * @since 13664 163 */ 164 default boolean isDrawable() { 165 return true; 166 } 167 168 /** 169 * Determines whether the primitive is selected 170 * @return whether the primitive is selected 171 * @since 13664 172 */ 173 default boolean isSelected() { 174 return false; 175 } 176 177 /** 178 * Determines if this primitive is a member of a selected relation. 179 * @return {@code true} if this primitive is a member of a selected relation, {@code false} otherwise 180 * @since 13664 181 */ 182 default boolean isMemberOfSelected() { 183 return false; 184 } 185 186 /** 187 * Determines if this primitive is an outer member of a selected multipolygon relation. 188 * @return {@code true} if this primitive is an outer member of a selected multipolygon relation, {@code false} otherwise 189 * @since 13664 190 */ 191 default boolean isOuterMemberOfSelected() { 192 return false; 193 } 194 195 /** 196 * Replies the id of this primitive. 197 * 198 * @return the id of this primitive. 199 */ 200 long getId(); 201 202 /** 203 * Replies the OSM id of this primitive. 204 * By default, returns the same value as {@link #getId}. 205 * Can be overridden by primitive implementations handling an internal id different from the OSM one. 206 * 207 * @return the OSM id of this primitive. 208 * @since 13924 209 */ 210 default long getOsmId() { 211 return getId(); 212 } 213 214 /** 215 * Replies the OSM primitive id for this primitive. 216 * 217 * @return the OSM primitive id for this primitive 218 * @see #getOsmId 219 * @since 13924 220 */ 221 default PrimitiveId getOsmPrimitiveId() { 222 return new SimplePrimitiveId(getOsmId(), getType()); 223 } 224 225 /** 226 * Replies the unique primitive id for this primitive. 227 * 228 * @return the unique primitive id for this primitive 229 * @see #getUniqueId 230 */ 231 default PrimitiveId getPrimitiveId() { 232 return new SimplePrimitiveId(getUniqueId(), getType()); 233 } 234 235 /** 236 * Replies the version number as returned by the API. The version is 0 if the id is 0 or 237 * if this primitive is incomplete. 238 * @return the version number as returned by the API 239 * 240 * @see PrimitiveData#setVersion(int) 241 */ 242 int getVersion(); 243 244 /** 245 * Sets the id and the version of this primitive if it is known to the OSM API. 246 * 247 * Since we know the id and its version it can't be incomplete anymore. incomplete 248 * is set to false. 249 * 250 * @param id the id. > 0 required 251 * @param version the version > 0 required 252 * @throws IllegalArgumentException if id <= 0 253 * @throws IllegalArgumentException if version <= 0 254 * @throws DataIntegrityProblemException if id is changed and primitive was already added to the dataset 255 */ 256 void setOsmId(long id, int version); 257 258 /** 259 * Replies the user who has last touched this object. May be null. 260 * 261 * @return the user who has last touched this object. May be null. 262 */ 263 User getUser(); 264 265 /** 266 * Sets the user who has last touched this object. 267 * 268 * @param user the user 269 */ 270 void setUser(User user); 271 272 /** 273 * Time of last modification to this object. This is not set by JOSM but 274 * read from the server and delivered back to the server unmodified. It is 275 * used to check against edit conflicts. 276 * 277 * @return date of last modification 278 * @see #setTimestamp 279 * @deprecated Use {@link #getInstant} 280 */ 281 @Deprecated 282 Date getTimestamp(); 283 284 /** 285 * Time of last modification to this object. This is not set by JOSM but 286 * read from the server and delivered back to the server unmodified. It is 287 * used to check against edit conflicts. 288 * 289 * @return date of last modification 290 * @see #getInstant 291 */ 292 Instant getInstant(); 293 294 /** 295 * Time of last modification to this object. This is not set by JOSM but 296 * read from the server and delivered back to the server unmodified. It is 297 * used to check against edit conflicts. 298 * 299 * @return last modification as timestamp 300 * @see #setRawTimestamp 301 */ 302 int getRawTimestamp(); 303 304 /** 305 * Sets time of last modification to this object 306 * @param timestamp date of last modification 307 * @see #getTimestamp 308 * @deprecated Use {@link #setInstant} 309 */ 310 @Deprecated 311 void setTimestamp(Date timestamp); 312 313 /** 314 * Sets time of last modification to this object 315 * @param timestamp date of last modification 316 * @see #getInstant 317 */ 318 void setInstant(Instant timestamp); 319 320 /** 321 * Sets time of last modification to this object 322 * @param timestamp date of last modification 323 * @see #getRawTimestamp 324 */ 325 void setRawTimestamp(int timestamp); 326 327 /** 328 * Determines if this primitive has no timestamp information. 329 * @return {@code true} if this primitive has no timestamp information 330 * @see #getTimestamp 331 * @see #getRawTimestamp 332 */ 333 boolean isTimestampEmpty(); 334 335 /** 336 * Replies the id of the changeset this primitive was last uploaded to. 337 * 0 if this primitive wasn't uploaded to a changeset yet or if the 338 * changeset isn't known. 339 * 340 * @return the id of the changeset this primitive was last uploaded to. 341 */ 342 int getChangesetId(); 343 344 /** 345 * Sets the changeset id of this primitive. Can't be set on a new primitive. 346 * 347 * @param changesetId the id. >= 0 required. 348 * @throws IllegalStateException if this primitive is new. 349 * @throws IllegalArgumentException if id < 0 350 */ 351 void setChangesetId(int changesetId); 352 353 /** 354 * Makes the given visitor visit this primitive. 355 * @param visitor visitor 356 */ 357 void accept(PrimitiveVisitor visitor); 358 359 /** 360 * <p>Visits {@code visitor} for all referrers.</p> 361 * 362 * @param visitor the visitor. Ignored, if null. 363 * @since 13806 364 */ 365 void visitReferrers(PrimitiveVisitor visitor); 366 367 /** 368 * Replies the name of this primitive. The default implementation replies the value 369 * of the tag <code>name</code> or null, if this tag is not present. 370 * 371 * @return the name of this primitive 372 */ 373 default String getName() { 374 return get("name"); 375 } 376 377 /** 378 * Replies a localized name for this primitive given by the value of the name tags 379 * accessed from very specific (language variant) to more generic (default name). 380 * 381 * @return the name of this primitive, <code>null</code> if no name exists 382 * @see LanguageInfo#getLanguageCodes 383 */ 384 default String getLocalName() { 385 for (String s : LanguageInfo.getLanguageCodes(null)) { 386 String val = get("name:" + s); 387 if (val != null) 388 return val; 389 } 390 391 return getName(); 392 } 393 394 /** 395 * Get an object to synchronize the style cache on. This <i>should</i> be a field that does not change during paint. 396 * By default, it returns the current object, but should be overriden to avoid some performance issues. 397 * @return A non-{@code null} object to synchronize on when painting 398 */ 399 default Object getStyleCacheSyncObject() { 400 return this; 401 } 402 403 /** 404 * Replies the display name of a primitive formatted by <code>formatter</code> 405 * @param formatter formatter to use 406 * 407 * @return the display name 408 * @since 13564 409 */ 410 String getDisplayName(NameFormatter formatter); 411 412 /** 413 * Gets the type this primitive is displayed at 414 * @return A {@link OsmPrimitiveType} 415 * @since 13564 416 */ 417 default OsmPrimitiveType getDisplayType() { 418 return getType(); 419 } 420 421 /** 422 * Updates the highlight flag for this primitive. 423 * @param highlighted The new highlight flag. 424 * @since 13664 425 */ 426 void setHighlighted(boolean highlighted); 427 428 /** 429 * Checks if the highlight flag for this primitive was set 430 * @return The highlight flag. 431 * @since 13664 432 */ 433 boolean isHighlighted(); 434 435 /** 436 * Determines if this object is considered "tagged". To be "tagged", an object 437 * must have one or more "interesting" tags. "created_by" and "source" 438 * are typically considered "uninteresting" and do not make an object "tagged". 439 * @return true if this object is considered "tagged" 440 * @since 13662 441 */ 442 boolean isTagged(); 443 444 /** 445 * Determines if this object is considered "annotated". To be "annotated", an object 446 * must have one or more "work in progress" tags, such as "note" or "fixme". 447 * @return true if this object is considered "annotated" 448 * @since 13662 449 */ 450 boolean isAnnotated(); 451 452 /** 453 * Determines if this object is a relation and behaves as a multipolygon. 454 * @return {@code true} if it is a real multipolygon or a boundary relation 455 * @since 13667 456 */ 457 default boolean isMultipolygon() { 458 return false; 459 } 460 461 /** 462 * true if this object has direction dependent tags (e.g. oneway) 463 * @return {@code true} if this object has direction dependent tags 464 * @since 13662 465 */ 466 boolean hasDirectionKeys(); 467 468 /** 469 * true if this object has the "reversed direction" flag enabled 470 * @return {@code true} if this object has the "reversed direction" flag enabled 471 * @since 13662 472 */ 473 boolean reversedDirection(); 474 475 /** 476 * Fetches the bounding box of the primitive. 477 * Since 17752, the returned bounding box might be immutable, i.e., modifying calls throw an {@link UnsupportedOperationException}. 478 * @return Bounding box of the object 479 * @since 13764 480 */ 481 @Override 482 BBox getBBox(); 483 484 /** 485 * Gets a list of all primitives in the current dataset that reference this primitive. 486 * @return The referrers 487 * @since 13764 488 */ 489 default List<? extends IPrimitive> getReferrers() { 490 return getReferrers(false); 491 } 492 493 /** 494 * Find primitives that reference this primitive. Returns only primitives that are included in the same 495 * dataset as this primitive. <br> 496 * 497 * For example following code will add wnew as referer to all nodes of existingWay, but this method will 498 * not return wnew because it's not part of the dataset <br> 499 * 500 * <code>Way wnew = new Way(existingWay)</code> 501 * 502 * @param allowWithoutDataset If true, method will return empty list if primitive is not part of the dataset. If false, 503 * exception will be thrown in this case 504 * 505 * @return a collection of all primitives that reference this primitive. 506 * @since 13808 507 */ 508 List<? extends IPrimitive> getReferrers(boolean allowWithoutDataset); 509 510 /** 511 * Returns the parent data set of this primitive. 512 * @return OsmData this primitive is part of. 513 * @since 13807 514 */ 515 OsmData<?, ?, ?, ?> getDataSet(); 516 517 /** 518 * Returns {@link #getKeys()} for which {@code key} does not fulfill uninteresting criteria. 519 * @return A map of interesting tags 520 * @since 13809 521 */ 522 Map<String, String> getInterestingTags(); 523 524 /** 525 * Replies true if other isn't null and has the same interesting tags (key/value-pairs) as this. 526 * 527 * @param other the other object primitive 528 * @return true if other isn't null and has the same interesting tags (key/value-pairs) as this. 529 * @since 13809 530 */ 531 default boolean hasSameInterestingTags(IPrimitive other) { 532 return (!hasKeys() && !other.hasKeys()) 533 || getInterestingTags().equals(other.getInterestingTags()); 534 } 535 536 /** 537 * Resets primitive children, if applicable. 538 * @param p primitive 539 * @since 17981 540 */ 541 static void resetPrimitiveChildren(IPrimitive p) { 542 if (p instanceof IWay<?>) { 543 ((IWay<?>) p).setNodes(null); 544 } else if (p instanceof IRelation<?>) { 545 ((IRelation<?>) p).setMembers(null); 546 } 547 } 548}