Changeset 3342 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2010-06-26T16:44:15+02:00 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
r3341 r3342 184 184 } 185 185 186 /* mappaint data */ 187 public ElemStyle mappaintStyle = null; 188 public int mappaintDrawnCode = 0; 189 190 /* This should not be called from outside. Fixing the UI to add relevant 191 get/set functions calling this implicitely is preferred, so we can have 192 transparent cache handling in the future. */ 193 protected void clearCached() 194 { 195 mappaintDrawnCode = 0; 196 mappaintStyle = null; 197 } 198 /* end of mappaint data */ 199 200 /** 201 * Unique identifier in OSM. This is used to identify objects on the server. 202 * An id of 0 means an unknown id. The object has not been uploaded yet to 203 * know what id it will get. 204 * 205 */ 206 private long id = 0; 207 208 /** the parent dataset */ 209 private DataSet dataSet; 210 211 /** 212 * This method should never ever by called from somewhere else than Dataset.addPrimitive or removePrimitive methods 213 * @param dataSet 214 */ 215 void setDataset(DataSet dataSet) { 216 if (this.dataSet != null && dataSet != null && this.dataSet != dataSet) 217 throw new DataIntegrityProblemException("Primitive cannot be included in more than one Dataset"); 218 this.dataSet = dataSet; 219 } 220 221 /** 222 * 223 * @return DataSet this primitive is part of. 224 */ 225 public DataSet getDataSet() { 226 return dataSet; 227 } 228 229 /** 230 * Throws exception if primitive is not part of the dataset 231 */ 232 public void checkDataset() { 233 if (dataSet == null) 234 throw new DataIntegrityProblemException("Primitive must be part of the dataset: " + toString()); 235 } 236 237 private volatile short flags = FLAG_VISIBLE; // visible per default 238 239 /** 240 * User that last modified this primitive, as specified by the server. 241 * Never changed by JOSM. 242 */ 243 private User user = null; 244 245 /** 246 * Contains the version number as returned by the API. Needed to 247 * ensure update consistency 248 */ 249 private int version = 0; 250 251 /** 252 * The id of the changeset this primitive was last uploaded to. 253 * 0 if it wasn't uploaded to a changeset yet of if the changeset 254 * id isn't known. 255 */ 256 private int changesetId; 186 /** 187 * Some predicates, that describe conditions on primitives. 188 */ 189 public static final Predicate<OsmPrimitive> isUsablePredicate = new Predicate<OsmPrimitive>() { 190 public boolean evaluate(OsmPrimitive primitive) { 191 return primitive.isUsable(); 192 } 193 }; 194 195 public static final Predicate<OsmPrimitive> isSelectablePredicate = new Predicate<OsmPrimitive>() { 196 public boolean evaluate(OsmPrimitive primitive) { 197 return primitive.isSelectable(); 198 } 199 }; 200 201 public static final Predicate<OsmPrimitive> nonDeletedPredicate = new Predicate<OsmPrimitive>() { 202 public boolean evaluate(OsmPrimitive primitive) { 203 return !primitive.isDeleted(); 204 } 205 }; 206 207 public static final Predicate<OsmPrimitive> nonDeletedCompletePredicate = new Predicate<OsmPrimitive>() { 208 public boolean evaluate(OsmPrimitive primitive) { 209 return !primitive.isDeleted() && !primitive.isIncomplete(); 210 } 211 }; 212 213 public static final Predicate<OsmPrimitive> nonDeletedPhysicalPredicate = new Predicate<OsmPrimitive>() { 214 public boolean evaluate(OsmPrimitive primitive) { 215 return !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof Relation); 216 } 217 }; 218 219 public static final Predicate<OsmPrimitive> modifiedPredicate = new Predicate<OsmPrimitive>() { 220 public boolean evaluate(OsmPrimitive primitive) { 221 return primitive.isModified(); 222 } 223 }; 224 225 public static final Predicate<OsmPrimitive> nodePredicate = new Predicate<OsmPrimitive>() { 226 public boolean evaluate(OsmPrimitive primitive) { 227 return primitive.getClass() == Node.class; 228 } 229 }; 230 231 public static final Predicate<OsmPrimitive> wayPredicate = new Predicate<OsmPrimitive>() { 232 public boolean evaluate(OsmPrimitive primitive) { 233 return primitive.getClass() == Way.class; 234 } 235 }; 236 237 public static final Predicate<OsmPrimitive> relationPredicate = new Predicate<OsmPrimitive>() { 238 public boolean evaluate(OsmPrimitive primitive) { 239 return primitive.getClass() == Relation.class; 240 } 241 }; 242 243 public static final Predicate<OsmPrimitive> allPredicate = new Predicate<OsmPrimitive>() { 244 public boolean evaluate(OsmPrimitive primitive) { 245 return true; 246 } 247 }; 257 248 258 249 /** … … 304 295 } 305 296 306 /* ------------------------------------------------------------------------------------ */ 307 /* accessors */ 308 /* ------------------------------------------------------------------------------------ */ 309 310 /** 311 * Make the primitive disabled (e.g. if a filter applies). 312 * To enable the primitive again, use unsetDisabledState. 313 * @param hide if the primitive should be completely hidden from view or 314 * just shown in gray color. 315 */ 316 public void setDisabledState(boolean hide) { 317 flags |= FLAG_DISABLED; 318 if (hide) { 319 flags |= FLAG_HIDE_IF_DISABLED; 320 } else { 321 flags &= ~FLAG_HIDE_IF_DISABLED; 322 } 323 } 324 325 /** 326 * Remove the disabled flag from the primitive. 327 * Afterwards, the primitive is displayed normally and can be selected 328 * again. 329 */ 330 public void unsetDisabledState() { 331 flags &= ~FLAG_DISABLED; 332 flags &= ~FLAG_HIDE_IF_DISABLED; 333 } 334 335 /** 336 * Replies true, if this primitive is disabled. (E.g. a filter 337 * applies) 338 */ 339 public boolean isDisabled() { 340 return (flags & FLAG_DISABLED) != 0; 341 } 342 343 /** 344 * Replies true, if this primitive is disabled and marked as 345 * completely hidden on the map. 346 */ 347 public boolean isDisabledAndHidden() { 348 return (((flags & FLAG_DISABLED) != 0) && ((flags & FLAG_HIDE_IF_DISABLED) != 0)); 349 } 350 351 @Deprecated 352 public boolean isFiltered() { 353 return isDisabledAndHidden(); 354 } 355 356 /** 357 * Marks this primitive as being modified. 358 * 359 * @param modified true, if this primitive is to be modified 360 */ 361 public void setModified(boolean modified) { 362 if (modified) { 363 flags |= FLAG_MODIFIED; 364 } else { 365 flags &= ~FLAG_MODIFIED; 366 } 367 } 368 369 /** 370 * Replies <code>true</code> if the object has been modified since it was loaded from 371 * the server. In this case, on next upload, this object will be updated. 372 * 373 * Deleted objects are deleted from the server. If the objects are added (id=0), 374 * the modified is ignored and the object is added to the server. 375 * 376 * @return <code>true</code> if the object has been modified since it was loaded from 377 * the server 378 */ 379 public boolean isModified() { 380 return (flags & FLAG_MODIFIED) != 0; 381 } 382 383 /** 384 * Replies <code>true</code>, if the object has been deleted. 385 * 386 * @return <code>true</code>, if the object has been deleted. 387 * @see #setDeleted(boolean) 388 */ 389 public boolean isDeleted() { 390 return (flags & FLAG_DELETED) != 0; 391 } 392 393 /** 394 * Replies <code>true</code> if the object has been deleted on the server and was undeleted by the user. 395 * @return <code>true</code> if the object has been undeleted 396 */ 397 public boolean isUndeleted() { 398 return (flags & (FLAG_VISIBLE + FLAG_DELETED)) == 0; 399 } 400 401 /** 402 * Replies <code>true</code>, if the object is usable (i.e. complete 403 * and not deleted). 404 * 405 * @return <code>true</code>, if the object is usable. 406 * @see #delete(boolean) 407 */ 408 public boolean isUsable() { 409 return (flags & (FLAG_DELETED + FLAG_INCOMPLETE)) == 0; 410 } 411 412 public boolean isSelectable() { 413 return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_DISABLED + FLAG_HIDE_IF_DISABLED)) == 0; 414 } 415 416 public boolean isDrawable() { 417 return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_HIDE_IF_DISABLED)) == 0; 418 } 419 420 /** 421 * Some predicates, that describe conditions on primitives. 422 */ 423 public static Predicate<OsmPrimitive> isUsablePredicate = new Predicate<OsmPrimitive>() { 424 public boolean evaluate(OsmPrimitive primitive) { 425 return primitive.isUsable(); 426 } 427 }; 428 429 public static Predicate<OsmPrimitive> isSelectablePredicate = new Predicate<OsmPrimitive>() { 430 public boolean evaluate(OsmPrimitive primitive) { 431 return primitive.isSelectable(); 432 } 433 }; 434 435 public static Predicate<OsmPrimitive> nonDeletedPredicate = new Predicate<OsmPrimitive>() { 436 public boolean evaluate(OsmPrimitive primitive) { 437 return !primitive.isDeleted(); 438 } 439 }; 440 441 public static Predicate<OsmPrimitive> nonDeletedCompletePredicate = new Predicate<OsmPrimitive>() { 442 public boolean evaluate(OsmPrimitive primitive) { 443 return !primitive.isDeleted() && !primitive.isIncomplete(); 444 } 445 }; 446 447 public static Predicate<OsmPrimitive> nonDeletedPhysicalPredicate = new Predicate<OsmPrimitive>() { 448 public boolean evaluate(OsmPrimitive primitive) { 449 return !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof Relation); 450 } 451 }; 452 453 public static Predicate<OsmPrimitive> modifiedPredicate = new Predicate<OsmPrimitive>() { 454 public boolean evaluate(OsmPrimitive primitive) { 455 return primitive.isModified(); 456 } 457 }; 458 459 public static Predicate<OsmPrimitive> nodePredicate = new Predicate<OsmPrimitive>() { 460 public boolean evaluate(OsmPrimitive primitive) { 461 return primitive.getClass() == Node.class; 462 } 463 }; 464 465 public static Predicate<OsmPrimitive> wayPredicate = new Predicate<OsmPrimitive>() { 466 public boolean evaluate(OsmPrimitive primitive) { 467 return primitive.getClass() == Way.class; 468 } 469 }; 470 471 public static Predicate<OsmPrimitive> relationPredicate = new Predicate<OsmPrimitive>() { 472 public boolean evaluate(OsmPrimitive primitive) { 473 return primitive.getClass() == Relation.class; 474 } 475 }; 476 477 public static Predicate<OsmPrimitive> allPredicate = new Predicate<OsmPrimitive>() { 478 public boolean evaluate(OsmPrimitive primitive) { 479 return true; 480 } 481 }; 482 483 484 /** 485 * Replies true if this primitive is either unknown to the server (i.e. its id 486 * is 0) or it is known to the server and it hasn't be deleted on the server. 487 * Replies false, if this primitive is known on the server and has been deleted 488 * on the server. 489 * 490 * @see #setVisible(boolean) 491 */ 492 public boolean isVisible() { 493 return (flags & FLAG_VISIBLE) != 0; 494 } 495 496 /** 497 * Sets whether this primitive is visible, i.e. whether it is known on the server 498 * and not deleted on the server. 499 * 500 * @see #isVisible() 501 * @throws IllegalStateException thrown if visible is set to false on an primitive with 502 * id==0 503 */ 504 public void setVisible(boolean visible) throws IllegalStateException{ 505 if (isNew() && visible == false) 506 throw new IllegalStateException(tr("A primitive with ID = 0 cannot be invisible.")); 507 if (visible) { 508 flags |= FLAG_VISIBLE; 509 } else { 510 flags &= ~FLAG_VISIBLE; 511 } 512 } 297 298 /*---------- 299 * MAPPAINT 300 *--------*/ 301 public ElemStyle mappaintStyle = null; 302 public int mappaintDrawnCode = 0; 303 304 /* This should not be called from outside. Fixing the UI to add relevant 305 get/set functions calling this implicitely is preferred, so we can have 306 transparent cache handling in the future. */ 307 protected void clearCached() 308 { 309 mappaintDrawnCode = 0; 310 mappaintStyle = null; 311 } 312 /* end of mappaint data */ 313 314 /*--------- 315 * DATASET 316 *---------*/ 317 318 /** the parent dataset */ 319 private DataSet dataSet; 320 321 /** 322 * This method should never ever by called from somewhere else than Dataset.addPrimitive or removePrimitive methods 323 * @param dataSet 324 */ 325 void setDataset(DataSet dataSet) { 326 if (this.dataSet != null && dataSet != null && this.dataSet != dataSet) 327 throw new DataIntegrityProblemException("Primitive cannot be included in more than one Dataset"); 328 this.dataSet = dataSet; 329 } 330 331 /** 332 * 333 * @return DataSet this primitive is part of. 334 */ 335 public DataSet getDataSet() { 336 return dataSet; 337 } 338 339 /** 340 * Throws exception if primitive is not part of the dataset 341 */ 342 public void checkDataset() { 343 if (dataSet == null) 344 throw new DataIntegrityProblemException("Primitive must be part of the dataset: " + toString()); 345 } 346 347 /*------------------- 348 * OTHER PROPERTIES 349 *-------------------/ 350 351 /** 352 * Unique identifier in OSM. This is used to identify objects on the server. 353 * An id of 0 means an unknown id. The object has not been uploaded yet to 354 * know what id it will get. 355 * 356 */ 357 private long id = 0; 358 359 /** 360 * User that last modified this primitive, as specified by the server. 361 * Never changed by JOSM. 362 */ 363 private User user = null; 364 365 /** 366 * Contains the version number as returned by the API. Needed to 367 * ensure update consistency 368 */ 369 private int version = 0; 370 371 /** 372 * The id of the changeset this primitive was last uploaded to. 373 * 0 if it wasn't uploaded to a changeset yet of if the changeset 374 * id isn't known. 375 */ 376 private int changesetId; 513 377 514 378 /** … … 604 468 } 605 469 606 public void setTimestamp(Date timestamp) {607 this.timestamp = (int)(timestamp.getTime() / 1000);608 }609 610 /**611 * Time of last modification to this object. This is not set by JOSM but612 * read from the server and delivered back to the server unmodified. It is613 * used to check against edit conflicts.614 *615 */616 public Date getTimestamp() {617 return new Date(timestamp * 1000l);618 }619 620 public boolean isTimestampEmpty() {621 return timestamp == 0;622 }623 624 private int timestamp;625 626 private static volatile Collection<String> uninteresting = null;627 /**628 * Contains a list of "uninteresting" keys that do not make an object629 * "tagged". Entries that end with ':' are causing a whole namespace to be considered630 * "uninteresting". Only the first level namespace is considered.631 * Initialized by isUninterestingKey()632 */633 public static Collection<String> getUninterestingKeys() {634 if (uninteresting == null) {635 uninteresting = Main.pref.getCollection("tags.uninteresting",636 Arrays.asList(new String[]{"source", "source_ref", "source:", "note", "comment",637 "converted_by", "created_by", "watch", "watch:", "fixme", "FIXME",638 "description"}));639 }640 return uninteresting;641 }642 643 /**644 * Returns true if key is considered "uninteresting".645 */646 public static boolean isUninterestingKey(String key) {647 getUninterestingKeys();648 if (uninteresting.contains(key))649 return true;650 int pos = key.indexOf(':');651 if (pos > 0)652 return uninteresting.contains(key.substring(0, pos + 1));653 return false;654 }655 656 private static volatile Match directionKeys = null;657 private static volatile Match reversedDirectionKeys = null;658 659 /**660 * Contains a list of direction-dependent keys that make an object661 * direction dependent.662 * Initialized by checkDirectionTagged()663 */664 static {665 // Legacy support - convert list of keys to search pattern666 if (Main.pref.isCollection("tags.direction", false)) {667 System.out.println("Collection of keys in tags.direction is no longer supported, value will converted to search pattern");668 Collection<String> keys = Main.pref.getCollection("tags.direction", null);669 StringBuilder builder = new StringBuilder();670 for (String key:keys) {671 builder.append(key);672 builder.append("=* | ");673 }674 builder.delete(builder.length() - 3, builder.length());675 Main.pref.put("tags.direction", builder.toString());676 }677 678 // FIXME: incline=\"-*\" search pattern does not work.679 String reversedDirectionDefault = "oneway=\"-1\" | incline=down | incline=\"-*\"";680 681 String directionDefault = "oneway? | incline=* | aerialway=* | "+682 "waterway=stream | waterway=river | waterway=canal | waterway=drain | waterway=rapids | "+683 "\"piste:type\"=downhill | \"piste:type\"=sled | man_made=\"piste:halfpipe\" | "+684 "junction=roundabout";685 686 try {687 reversedDirectionKeys = SearchCompiler.compile(Main.pref.get("tags.reversed_direction", reversedDirectionDefault), false, false);688 } catch (ParseError e) {689 System.err.println("Unable to compile pattern for tags.reversed_direction, trying default pattern: " + e.getMessage());690 691 try {692 reversedDirectionKeys = SearchCompiler.compile(reversedDirectionDefault, false, false);693 } catch (ParseError e2) {694 throw new AssertionError("Unable to compile default pattern for direction keys: " + e2.getMessage());695 }696 }697 try {698 directionKeys = SearchCompiler.compile(Main.pref.get("tags.direction", directionDefault), false, false);699 } catch (ParseError e) {700 System.err.println("Unable to compile pattern for tags.direction, trying default pattern: " + e.getMessage());701 702 try {703 directionKeys = SearchCompiler.compile(directionDefault, false, false);704 } catch (ParseError e2) {705 throw new AssertionError("Unable to compile default pattern for direction keys: " + e2.getMessage());706 }707 }708 }709 710 /**711 * Replies a list of direction-dependent keys that make an object712 * direction dependent.713 *714 * @return a list of direction-dependent keys that make an object715 * direction dependent.716 */717 @Deprecated718 public static Collection<String> getDirectionKeys() {719 return Main.pref.getCollection("tags.direction",720 Arrays.asList("oneway","incline","incline_steep","aerialway"));721 }722 723 /**724 * Implementation of the visitor scheme. Subclasses have to call the correct725 * visitor function.726 * @param visitor The visitor from which the visit() function must be called.727 */728 abstract public void visit(Visitor visitor);729 730 /**731 * Sets whether this primitive is deleted or not.732 *733 * Also marks this primitive as modified if deleted is true.734 *735 * @param deleted true, if this primitive is deleted; false, otherwise736 */737 public void setDeleted(boolean deleted) {738 if (deleted) {739 flags |= FLAG_DELETED;740 } else {741 flags &= ~FLAG_DELETED;742 }743 setModified(deleted ^ !isVisible());744 if (dataSet != null) {745 if (deleted) {746 dataSet.firePrimitivesRemoved(Collections.singleton(this), false);747 } else {748 dataSet.firePrimitivesAdded(Collections.singleton(this), false);749 }750 }751 }752 753 470 /** 754 471 * Replies the user who has last touched this object. May be null. … … 803 520 804 521 /** 805 * Equal, if the id (and class) is equal. 806 * 807 * An primitive is equal to its incomplete counter part. 808 */ 809 @Override public boolean equals(Object obj) { 810 if (obj instanceof OsmPrimitive) 811 return ((OsmPrimitive)obj).id == id && obj.getClass() == getClass(); 522 * Replies the unique primitive id for this primitive 523 * 524 * @return the unique primitive id for this primitive 525 */ 526 public PrimitiveId getPrimitiveId() { 527 return new SimplePrimitiveId(getUniqueId(), getType()); 528 } 529 530 public void setTimestamp(Date timestamp) { 531 this.timestamp = (int)(timestamp.getTime() / 1000); 532 } 533 534 /** 535 * Time of last modification to this object. This is not set by JOSM but 536 * read from the server and delivered back to the server unmodified. It is 537 * used to check against edit conflicts. 538 * 539 */ 540 public Date getTimestamp() { 541 return new Date(timestamp * 1000l); 542 } 543 544 public boolean isTimestampEmpty() { 545 return timestamp == 0; 546 } 547 548 private int timestamp; 549 550 /* ------- 551 /* FLAGS 552 /* ------*/ 553 554 private volatile short flags = FLAG_VISIBLE; // visible per default 555 556 private void updateFlags(int flag, boolean value) { 557 if (value) { 558 flags |= flag; 559 } else { 560 flags &= ~flag; 561 } 562 } 563 564 /** 565 * Make the primitive disabled (e.g. if a filter applies). 566 * To enable the primitive again, use unsetDisabledState. 567 * @param hide if the primitive should be completely hidden from view or 568 * just shown in gray color. 569 */ 570 public void setDisabledState(boolean hide) { 571 flags |= FLAG_DISABLED; 572 if (hide) { 573 flags |= FLAG_HIDE_IF_DISABLED; 574 } else { 575 flags &= ~FLAG_HIDE_IF_DISABLED; 576 } 577 } 578 579 /** 580 * Remove the disabled flag from the primitive. 581 * Afterwards, the primitive is displayed normally and can be selected 582 * again. 583 */ 584 public void unsetDisabledState() { 585 updateFlags(FLAG_DISABLED + FLAG_HIDE_IF_DISABLED, false); 586 } 587 588 /** 589 * Replies true, if this primitive is disabled. (E.g. a filter 590 * applies) 591 */ 592 public boolean isDisabled() { 593 return (flags & FLAG_DISABLED) != 0; 594 } 595 596 /** 597 * Replies true, if this primitive is disabled and marked as 598 * completely hidden on the map. 599 */ 600 public boolean isDisabledAndHidden() { 601 return (((flags & FLAG_DISABLED) != 0) && ((flags & FLAG_HIDE_IF_DISABLED) != 0)); 602 } 603 604 @Deprecated 605 public boolean isFiltered() { 606 return isDisabledAndHidden(); 607 } 608 609 /** 610 * Marks this primitive as being modified. 611 * 612 * @param modified true, if this primitive is to be modified 613 */ 614 public void setModified(boolean modified) { 615 updateFlags(FLAG_MODIFIED, modified); 616 } 617 618 /** 619 * Replies <code>true</code> if the object has been modified since it was loaded from 620 * the server. In this case, on next upload, this object will be updated. 621 * 622 * Deleted objects are deleted from the server. If the objects are added (id=0), 623 * the modified is ignored and the object is added to the server. 624 * 625 * @return <code>true</code> if the object has been modified since it was loaded from 626 * the server 627 */ 628 public boolean isModified() { 629 return (flags & FLAG_MODIFIED) != 0; 630 } 631 632 /** 633 * Replies <code>true</code>, if the object has been deleted. 634 * 635 * @return <code>true</code>, if the object has been deleted. 636 * @see #setDeleted(boolean) 637 */ 638 public boolean isDeleted() { 639 return (flags & FLAG_DELETED) != 0; 640 } 641 642 /** 643 * Replies <code>true</code> if the object has been deleted on the server and was undeleted by the user. 644 * @return <code>true</code> if the object has been undeleted 645 */ 646 public boolean isUndeleted() { 647 return (flags & (FLAG_VISIBLE + FLAG_DELETED)) == 0; 648 } 649 650 /** 651 * Replies <code>true</code>, if the object is usable (i.e. complete 652 * and not deleted). 653 * 654 * @return <code>true</code>, if the object is usable. 655 * @see #delete(boolean) 656 */ 657 public boolean isUsable() { 658 return (flags & (FLAG_DELETED + FLAG_INCOMPLETE)) == 0; 659 } 660 661 public boolean isSelectable() { 662 return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_DISABLED + FLAG_HIDE_IF_DISABLED)) == 0; 663 } 664 665 public boolean isDrawable() { 666 return (flags & (FLAG_DELETED + FLAG_INCOMPLETE + FLAG_HIDE_IF_DISABLED)) == 0; 667 } 668 669 /** 670 * Replies true if this primitive is either unknown to the server (i.e. its id 671 * is 0) or it is known to the server and it hasn't be deleted on the server. 672 * Replies false, if this primitive is known on the server and has been deleted 673 * on the server. 674 * 675 * @see #setVisible(boolean) 676 */ 677 public boolean isVisible() { 678 return (flags & FLAG_VISIBLE) != 0; 679 } 680 681 /** 682 * Sets whether this primitive is visible, i.e. whether it is known on the server 683 * and not deleted on the server. 684 * 685 * @see #isVisible() 686 * @throws IllegalStateException thrown if visible is set to false on an primitive with 687 * id==0 688 */ 689 public void setVisible(boolean visible) throws IllegalStateException{ 690 if (isNew() && visible == false) 691 throw new IllegalStateException(tr("A primitive with ID = 0 cannot be invisible.")); 692 updateFlags(FLAG_VISIBLE, visible); 693 } 694 695 /** 696 * Sets whether this primitive is deleted or not. 697 * 698 * Also marks this primitive as modified if deleted is true. 699 * 700 * @param deleted true, if this primitive is deleted; false, otherwise 701 */ 702 public void setDeleted(boolean deleted) { 703 updateFlags(FLAG_DELETED, deleted); 704 setModified(deleted ^ !isVisible()); 705 if (dataSet != null) { 706 if (deleted) { 707 dataSet.firePrimitivesRemoved(Collections.singleton(this), false); 708 } else { 709 dataSet.firePrimitivesAdded(Collections.singleton(this), false); 710 } 711 } 712 } 713 714 715 /** 716 * If set to true, this object is incomplete, which means only the id 717 * and type is known (type is the objects instance class) 718 */ 719 private void setIncomplete(boolean incomplete) { 720 if (dataSet != null && incomplete != this.isIncomplete()) { 721 if (incomplete) { 722 dataSet.firePrimitivesRemoved(Collections.singletonList(this), true); 723 } else { 724 dataSet.firePrimitivesAdded(Collections.singletonList(this), true); 725 } 726 } 727 updateFlags(FLAG_INCOMPLETE, incomplete); 728 } 729 730 public boolean isIncomplete() { 731 return (flags & FLAG_INCOMPLETE) != 0; 732 } 733 734 public boolean isSelected() { 735 return dataSet != null && dataSet.isSelected(this); 736 } 737 738 public void setHighlighted(boolean highlighted) { 739 if (isHighlighted() != highlighted) { 740 updateFlags(FLAG_HIGHLIGHTED, highlighted); 741 if (dataSet != null) { 742 dataSet.fireHighlightingChanged(this); 743 } 744 } 745 } 746 747 public boolean isHighlighted() { 748 return (flags & FLAG_HIGHLIGHTED) != 0; 749 } 750 751 /*---------------------------------- 752 * UNINTERESTING AND DIRECTION KEYS 753 *----------------------------------*/ 754 755 756 private static volatile Collection<String> uninteresting = null; 757 /** 758 * Contains a list of "uninteresting" keys that do not make an object 759 * "tagged". Entries that end with ':' are causing a whole namespace to be considered 760 * "uninteresting". Only the first level namespace is considered. 761 * Initialized by isUninterestingKey() 762 */ 763 public static Collection<String> getUninterestingKeys() { 764 if (uninteresting == null) { 765 uninteresting = Main.pref.getCollection("tags.uninteresting", 766 Arrays.asList(new String[]{"source", "source_ref", "source:", "note", "comment", 767 "converted_by", "created_by", "watch", "watch:", "fixme", "FIXME", 768 "description"})); 769 } 770 return uninteresting; 771 } 772 773 /** 774 * Returns true if key is considered "uninteresting". 775 */ 776 public static boolean isUninterestingKey(String key) { 777 getUninterestingKeys(); 778 if (uninteresting.contains(key)) 779 return true; 780 int pos = key.indexOf(':'); 781 if (pos > 0) 782 return uninteresting.contains(key.substring(0, pos + 1)); 812 783 return false; 813 784 } 814 785 815 /** 816 * Return the id plus the class type encoded as hashcode or super's hashcode if id is 0. 817 * 818 * An primitive has the same hashcode as its incomplete counterpart. 819 */ 820 @Override public final int hashCode() { 821 return (int)id; 786 private static volatile Match directionKeys = null; 787 private static volatile Match reversedDirectionKeys = null; 788 789 /** 790 * Contains a list of direction-dependent keys that make an object 791 * direction dependent. 792 * Initialized by checkDirectionTagged() 793 */ 794 static { 795 // Legacy support - convert list of keys to search pattern 796 if (Main.pref.isCollection("tags.direction", false)) { 797 System.out.println("Collection of keys in tags.direction is no longer supported, value will converted to search pattern"); 798 Collection<String> keys = Main.pref.getCollection("tags.direction", null); 799 StringBuilder builder = new StringBuilder(); 800 for (String key:keys) { 801 builder.append(key); 802 builder.append("=* | "); 803 } 804 builder.delete(builder.length() - 3, builder.length()); 805 Main.pref.put("tags.direction", builder.toString()); 806 } 807 808 // FIXME: incline=\"-*\" search pattern does not work. 809 String reversedDirectionDefault = "oneway=\"-1\" | incline=down | incline=\"-*\""; 810 811 String directionDefault = "oneway? | incline=* | aerialway=* | "+ 812 "waterway=stream | waterway=river | waterway=canal | waterway=drain | waterway=rapids | "+ 813 "\"piste:type\"=downhill | \"piste:type\"=sled | man_made=\"piste:halfpipe\" | "+ 814 "junction=roundabout"; 815 816 try { 817 reversedDirectionKeys = SearchCompiler.compile(Main.pref.get("tags.reversed_direction", reversedDirectionDefault), false, false); 818 } catch (ParseError e) { 819 System.err.println("Unable to compile pattern for tags.reversed_direction, trying default pattern: " + e.getMessage()); 820 821 try { 822 reversedDirectionKeys = SearchCompiler.compile(reversedDirectionDefault, false, false); 823 } catch (ParseError e2) { 824 throw new AssertionError("Unable to compile default pattern for direction keys: " + e2.getMessage()); 825 } 826 } 827 try { 828 directionKeys = SearchCompiler.compile(Main.pref.get("tags.direction", directionDefault), false, false); 829 } catch (ParseError e) { 830 System.err.println("Unable to compile pattern for tags.direction, trying default pattern: " + e.getMessage()); 831 832 try { 833 directionKeys = SearchCompiler.compile(directionDefault, false, false); 834 } catch (ParseError e2) { 835 throw new AssertionError("Unable to compile default pattern for direction keys: " + e2.getMessage()); 836 } 837 } 838 } 839 840 private void updateTagged() { 841 if (keys != null) { 842 for (String key: keySet()) { 843 if (!isUninterestingKey(key)) { 844 updateFlags(FLAG_TAGGED, true); 845 return; 846 } 847 } 848 } 849 updateFlags(FLAG_TAGGED, false); 850 } 851 852 /** 853 * true if this object is considered "tagged". To be "tagged", an object 854 * must have one or more "interesting" tags. "created_by" and "source" 855 * are typically considered "uninteresting" and do not make an object 856 * "tagged". 857 */ 858 public boolean isTagged() { 859 return (flags & FLAG_TAGGED) != 0; 860 } 861 862 private void updateDirectionFlags() { 863 boolean hasDirections = false; 864 boolean directionReversed = false; 865 if (reversedDirectionKeys.match(this)) { 866 hasDirections = true; 867 directionReversed = true; 868 } 869 if (directionKeys.match(this)) { 870 hasDirections = true; 871 } 872 873 updateFlags(FLAG_DIRECTION_REVERSED, directionReversed); 874 updateFlags(FLAG_HAS_DIRECTIONS, hasDirections); 875 } 876 877 /** 878 * true if this object has direction dependent tags (e.g. oneway) 879 */ 880 public boolean hasDirectionKeys() { 881 return (flags & FLAG_HAS_DIRECTIONS) != 0; 882 } 883 884 public boolean reversedDirection() { 885 return (flags & FLAG_DIRECTION_REVERSED) != 0; 822 886 } 823 887 … … 1121 1185 } 1122 1186 1187 /*----------------- 1188 * OTHER METHODS 1189 *----------------/ 1190 1191 /** 1192 * Implementation of the visitor scheme. Subclasses have to call the correct 1193 * visitor function. 1194 * @param visitor The visitor from which the visit() function must be called. 1195 */ 1196 abstract public void visit(Visitor visitor); 1197 1198 1123 1199 /** 1124 1200 * Get and write all attributes from the parameter. Does not fire any listener, so … … 1230 1306 } 1231 1307 1232 private void updateTagged() {1233 if (keys != null) {1234 for (String key: keySet()) {1235 if (!isUninterestingKey(key)) {1236 flags |= FLAG_TAGGED;1237 return;1238 }1239 }1240 }1241 flags &= ~FLAG_TAGGED;1242 }1243 1244 /**1245 * true if this object is considered "tagged". To be "tagged", an object1246 * must have one or more "interesting" tags. "created_by" and "source"1247 * are typically considered "uninteresting" and do not make an object1248 * "tagged".1249 */1250 public boolean isTagged() {1251 return (flags & FLAG_TAGGED) != 0;1252 }1253 1254 private void updateDirectionFlags() {1255 boolean hasDirections = false;1256 boolean directionReversed = false;1257 if (reversedDirectionKeys.match(this)) {1258 hasDirections = true;1259 directionReversed = true;1260 }1261 if (directionKeys.match(this)) {1262 hasDirections = true;1263 }1264 1265 if (directionReversed) {1266 flags |= FLAG_DIRECTION_REVERSED;1267 } else {1268 flags &= ~FLAG_DIRECTION_REVERSED;1269 }1270 if (hasDirections) {1271 flags |= FLAG_HAS_DIRECTIONS;1272 } else {1273 flags &= ~FLAG_HAS_DIRECTIONS;1274 }1275 }1276 1277 /**1278 * true if this object has direction dependent tags (e.g. oneway)1279 */1280 public boolean hasDirectionKeys() {1281 return (flags & FLAG_HAS_DIRECTIONS) != 0;1282 }1283 1284 public boolean reversedDirection() {1285 return (flags & FLAG_DIRECTION_REVERSED) != 0;1286 }1287 1308 /** 1288 1309 * Replies the name of this primitive. The default implementation replies the value … … 1366 1387 } 1367 1388 1389 1390 public abstract BBox getBBox(); 1391 1392 /** 1393 * Called by Dataset to update cached position information of primitive (bbox, cached EarthNorth, ...) 1394 */ 1395 public abstract void updatePosition(); 1396 1397 /*---------------- 1398 * OBJECT METHODS 1399 *---------------*/ 1400 1368 1401 protected String getFlagsAsString() { 1369 1402 StringBuilder builder = new StringBuilder(); … … 1400 1433 } 1401 1434 1402 public abstract BBox getBBox(); 1403 1404 /** 1405 * Called by Dataset to update cached position information of primitive (bbox, cached EarthNorth, ...) 1406 */ 1407 public abstract void updatePosition(); 1408 1409 /** 1410 * Replies the unique primitive id for this primitive 1411 * 1412 * @return the unique primitive id for this primitive 1413 */ 1414 public PrimitiveId getPrimitiveId() { 1415 return new SimplePrimitiveId(getUniqueId(), getType()); 1416 } 1417 1418 /** 1419 * If set to true, this object is incomplete, which means only the id 1420 * and type is known (type is the objects instance class) 1421 */ 1422 private void setIncomplete(boolean incomplete) { 1423 if (dataSet != null && incomplete != this.isIncomplete()) { 1424 if (incomplete) { 1425 dataSet.firePrimitivesRemoved(Collections.singletonList(this), true); 1426 } else { 1427 dataSet.firePrimitivesAdded(Collections.singletonList(this), true); 1428 } 1429 } 1430 if (incomplete) { 1431 flags |= FLAG_INCOMPLETE; 1432 } else { 1433 flags &= ~FLAG_INCOMPLETE; 1434 } 1435 } 1436 1437 public boolean isIncomplete() { 1438 return (flags & FLAG_INCOMPLETE) != 0; 1439 } 1440 1441 public boolean isSelected() { 1442 return dataSet != null && dataSet.isSelected(this); 1443 } 1444 1445 public void setHighlighted(boolean highlighted) { 1446 if (isHighlighted() != highlighted) { 1447 if (highlighted) { 1448 flags |= FLAG_HIGHLIGHTED; 1449 } else { 1450 flags &= ~FLAG_HIGHLIGHTED; 1451 } 1452 if (dataSet != null) { 1453 dataSet.fireHighlightingChanged(this); 1454 } 1455 } 1456 } 1457 1458 public boolean isHighlighted() { 1459 return (flags & FLAG_HIGHLIGHTED) != 0; 1460 } 1435 /** 1436 * Equal, if the id (and class) is equal. 1437 * 1438 * An primitive is equal to its incomplete counter part. 1439 */ 1440 @Override public boolean equals(Object obj) { 1441 if (obj instanceof OsmPrimitive) 1442 return ((OsmPrimitive)obj).id == id && obj.getClass() == getClass(); 1443 return false; 1444 } 1445 1446 /** 1447 * Return the id plus the class type encoded as hashcode or super's hashcode if id is 0. 1448 * 1449 * An primitive has the same hashcode as its incomplete counterpart. 1450 */ 1451 @Override public final int hashCode() { 1452 return (int)id; 1453 } 1454 1461 1455 }
Note:
See TracChangeset
for help on using the changeset viewer.