Changeset 3348 in josm for trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
- Timestamp:
- 2010-06-27T17:07:49+02:00 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
r3316 r3348 15 15 import java.util.List; 16 16 import java.util.Map; 17 import java.util.concurrent.locks.Lock; 18 import java.util.concurrent.locks.ReadWriteLock; 19 import java.util.concurrent.locks.ReentrantReadWriteLock; 17 20 18 21 import org.openstreetmap.josm.data.SelectionChangedListener; … … 42 45 public class DataSet implements Cloneable { 43 46 47 /** 48 * Maximum number of events that can be fired between beginUpdate/endUpdate to be send as single events (ie without DatasetChangedEvent) 49 */ 50 private static final int MAX_SINGLE_EVENTS = 30; 51 52 /** 53 * Maximum number of events to kept between beginUpdate/endUpdate. When more events are created, that simple DatasetChangedEvent is sent) 54 */ 55 private static final int MAX_EVENTS = 1000; 56 44 57 private static class IdHash implements Hash<PrimitiveId,OsmPrimitive> { 45 58 … … 57 70 private Map<PrimitiveId, OsmPrimitive> primitivesMap = allPrimitives.foreignKey(new IdHash()); 58 71 private List<DataSetListener> listeners = new ArrayList<DataSetListener>(); 72 59 73 // Number of open calls to beginUpdate 60 74 private int updateCount; 75 // Events that occurred while dataset was locked but should be fired after write lock is released 76 private final List<AbstractDatasetChangedEvent> cachedEvents = new ArrayList<AbstractDatasetChangedEvent>(); 61 77 62 78 private int highlightUpdateCount; 79 80 private final ReadWriteLock lock = new ReentrantReadWriteLock(); 81 82 public Lock getReadLock() { 83 return lock.readLock(); 84 } 63 85 64 86 /** … … 212 234 */ 213 235 public void addPrimitive(OsmPrimitive primitive) { 214 if (getPrimitiveById(primitive) != null) 215 throw new DataIntegrityProblemException( 216 tr("Unable to add primitive {0} to the dataset because it is already included", primitive.toString())); 217 218 primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reinexRelation to work properly) 219 if (primitive instanceof Node) { 220 nodes.add((Node) primitive); 221 } else if (primitive instanceof Way) { 222 ways.add((Way) primitive); 223 } else if (primitive instanceof Relation) { 224 relations.add((Relation) primitive); 225 } 226 allPrimitives.add(primitive); 227 primitive.setDataset(this); 228 firePrimitivesAdded(Collections.singletonList(primitive), false); 236 beginUpdate(); 237 try { 238 if (getPrimitiveById(primitive) != null) 239 throw new DataIntegrityProblemException( 240 tr("Unable to add primitive {0} to the dataset because it is already included", primitive.toString())); 241 242 primitive.updatePosition(); // Set cached bbox for way and relation (required for reindexWay and reinexRelation to work properly) 243 if (primitive instanceof Node) { 244 nodes.add((Node) primitive); 245 } else if (primitive instanceof Way) { 246 ways.add((Way) primitive); 247 } else if (primitive instanceof Relation) { 248 relations.add((Relation) primitive); 249 } 250 allPrimitives.add(primitive); 251 primitive.setDataset(this); 252 firePrimitivesAdded(Collections.singletonList(primitive), false); 253 } finally { 254 endUpdate(); 255 } 229 256 } 230 257 231 258 public OsmPrimitive addPrimitive(PrimitiveData data) { 232 OsmPrimitive result; 233 if (data instanceof NodeData) { 234 result = new Node(); 235 } else if (data instanceof WayData) { 236 result = new Way(); 237 } else if (data instanceof RelationData) { 238 result = new Relation(); 239 } else 240 throw new AssertionError(); 241 result.setDataset(this); 242 result.load(data); 243 addPrimitive(result); 244 return result; 259 beginUpdate(); 260 try { 261 OsmPrimitive result; 262 if (data instanceof NodeData) { 263 result = new Node(); 264 } else if (data instanceof WayData) { 265 result = new Way(); 266 } else if (data instanceof RelationData) { 267 result = new Relation(); 268 } else 269 throw new AssertionError(); 270 result.setDataset(this); 271 result.load(data); 272 addPrimitive(result); 273 return result; 274 } finally { 275 endUpdate(); 276 } 245 277 } 246 278 … … 255 287 */ 256 288 public void removePrimitive(PrimitiveId primitiveId) { 257 OsmPrimitive primitive = getPrimitiveByIdChecked(primitiveId); 258 if (primitive == null) 259 return; 260 if (primitive instanceof Node) { 261 nodes.remove(primitive); 262 } else if (primitive instanceof Way) { 263 ways.remove(primitive); 264 } else if (primitive instanceof Relation) { 265 relations.remove(primitive); 266 } 267 selectedPrimitives.remove(primitive); 268 allPrimitives.remove(primitive); 269 primitive.setDataset(null); 270 firePrimitivesRemoved(Collections.singletonList(primitive), false); 289 beginUpdate(); 290 try { 291 OsmPrimitive primitive = getPrimitiveByIdChecked(primitiveId); 292 if (primitive == null) 293 return; 294 if (primitive instanceof Node) { 295 nodes.remove(primitive); 296 } else if (primitive instanceof Way) { 297 ways.remove(primitive); 298 } else if (primitive instanceof Relation) { 299 relations.remove(primitive); 300 } 301 selectedPrimitives.remove(primitive); 302 allPrimitives.remove(primitive); 303 primitive.setDataset(null); 304 firePrimitivesRemoved(Collections.singletonList(primitive), false); 305 } finally { 306 endUpdate(); 307 } 271 308 } 272 309 … … 492 529 */ 493 530 494 // public void setDisabled(OsmPrimitive... osm) {495 // if (osm.length == 1 && osm[0] == null) {496 // setDisabled();497 // return;498 // }499 // clearDisabled(allPrimitives());500 // for (OsmPrimitive o : osm)501 // if (o != null) {502 // o.setDisabled(true);503 // }504 // }505 //506 // public void setDisabled(Collection<? extends OsmPrimitive> selection) {507 // clearDisabled(nodes);508 // clearDisabled(ways);509 // clearDisabled(relations);510 // for (OsmPrimitive osm : selection) {511 // osm.setDisabled(true);512 // }513 // }514 //515 // /**516 // * Remove the disabled parameter from every value in the collection.517 // * @param list The collection to remove the disabled parameter from.518 // */519 // private void clearDisabled(Collection<? extends OsmPrimitive> list) {520 // for (OsmPrimitive osm : list) {521 // osm.setDisabled(false);522 // }523 // }524 //525 //526 // public void setFiltered(Collection<? extends OsmPrimitive> selection) {527 // clearFiltered(nodes);528 // clearFiltered(ways);529 // clearFiltered(relations);530 // for (OsmPrimitive osm : selection) {531 // osm.setFiltered(true);532 // }533 // }534 //535 // public void setFiltered(OsmPrimitive... osm) {536 // if (osm.length == 1 && osm[0] == null) {537 // setFiltered();538 // return;539 // }540 // clearFiltered(nodes);541 // clearFiltered(ways);542 // clearFiltered(relations);543 // for (OsmPrimitive o : osm)544 // if (o != null) {545 // o.setFiltered(true);546 // }547 // }548 //549 // /**550 // * Remove the filtered parameter from every value in the collection.551 // * @param list The collection to remove the filtered parameter from.552 // */553 // private void clearFiltered(Collection<? extends OsmPrimitive> list) {554 // if (list == null)555 // return;556 // for (OsmPrimitive osm : list) {557 // osm.setFiltered(false);558 // }559 // }531 // public void setDisabled(OsmPrimitive... osm) { 532 // if (osm.length == 1 && osm[0] == null) { 533 // setDisabled(); 534 // return; 535 // } 536 // clearDisabled(allPrimitives()); 537 // for (OsmPrimitive o : osm) 538 // if (o != null) { 539 // o.setDisabled(true); 540 // } 541 // } 542 // 543 // public void setDisabled(Collection<? extends OsmPrimitive> selection) { 544 // clearDisabled(nodes); 545 // clearDisabled(ways); 546 // clearDisabled(relations); 547 // for (OsmPrimitive osm : selection) { 548 // osm.setDisabled(true); 549 // } 550 // } 551 // 552 // /** 553 // * Remove the disabled parameter from every value in the collection. 554 // * @param list The collection to remove the disabled parameter from. 555 // */ 556 // private void clearDisabled(Collection<? extends OsmPrimitive> list) { 557 // for (OsmPrimitive osm : list) { 558 // osm.setDisabled(false); 559 // } 560 // } 561 // 562 // 563 // public void setFiltered(Collection<? extends OsmPrimitive> selection) { 564 // clearFiltered(nodes); 565 // clearFiltered(ways); 566 // clearFiltered(relations); 567 // for (OsmPrimitive osm : selection) { 568 // osm.setFiltered(true); 569 // } 570 // } 571 // 572 // public void setFiltered(OsmPrimitive... osm) { 573 // if (osm.length == 1 && osm[0] == null) { 574 // setFiltered(); 575 // return; 576 // } 577 // clearFiltered(nodes); 578 // clearFiltered(ways); 579 // clearFiltered(relations); 580 // for (OsmPrimitive o : osm) 581 // if (o != null) { 582 // o.setFiltered(true); 583 // } 584 // } 585 // 586 // /** 587 // * Remove the filtered parameter from every value in the collection. 588 // * @param list The collection to remove the filtered parameter from. 589 // */ 590 // private void clearFiltered(Collection<? extends OsmPrimitive> list) { 591 // if (list == null) 592 // return; 593 // for (OsmPrimitive osm : list) { 594 // osm.setFiltered(false); 595 // } 596 // } 560 597 561 598 @Override public DataSet clone() { 562 DataSet ds = new DataSet(); 563 HashMap<OsmPrimitive, OsmPrimitive> primitivesMap = new HashMap<OsmPrimitive, OsmPrimitive>(); 564 for (Node n : nodes) { 565 Node newNode = new Node(n); 566 primitivesMap.put(n, newNode); 567 ds.addPrimitive(newNode); 568 } 569 for (Way w : ways) { 570 Way newWay = new Way(w); 571 primitivesMap.put(w, newWay); 572 List<Node> newNodes = new ArrayList<Node>(); 573 for (Node n: w.getNodes()) { 574 newNodes.add((Node)primitivesMap.get(n)); 575 } 576 newWay.setNodes(newNodes); 577 ds.addPrimitive(newWay); 578 } 579 // Because relations can have other relations as members we first clone all relations 580 // and then get the cloned members 581 for (Relation r : relations) { 582 Relation newRelation = new Relation(r, r.isNew()); 583 newRelation.setMembers(null); 584 primitivesMap.put(r, newRelation); 585 ds.addPrimitive(newRelation); 586 } 587 for (Relation r : relations) { 588 Relation newRelation = (Relation)primitivesMap.get(r); 589 List<RelationMember> newMembers = new ArrayList<RelationMember>(); 590 for (RelationMember rm: r.getMembers()) { 591 newMembers.add(new RelationMember(rm.getRole(), primitivesMap.get(rm.getMember()))); 592 } 593 newRelation.setMembers(newMembers); 594 } 595 for (DataSource source : dataSources) { 596 ds.dataSources.add(new DataSource(source.bounds, source.origin)); 597 } 598 ds.version = version; 599 return ds; 599 getReadLock().lock(); 600 try { 601 DataSet ds = new DataSet(); 602 HashMap<OsmPrimitive, OsmPrimitive> primitivesMap = new HashMap<OsmPrimitive, OsmPrimitive>(); 603 for (Node n : nodes) { 604 Node newNode = new Node(n); 605 primitivesMap.put(n, newNode); 606 ds.addPrimitive(newNode); 607 } 608 for (Way w : ways) { 609 Way newWay = new Way(w); 610 primitivesMap.put(w, newWay); 611 List<Node> newNodes = new ArrayList<Node>(); 612 for (Node n: w.getNodes()) { 613 newNodes.add((Node)primitivesMap.get(n)); 614 } 615 newWay.setNodes(newNodes); 616 ds.addPrimitive(newWay); 617 } 618 // Because relations can have other relations as members we first clone all relations 619 // and then get the cloned members 620 for (Relation r : relations) { 621 Relation newRelation = new Relation(r, r.isNew()); 622 newRelation.setMembers(null); 623 primitivesMap.put(r, newRelation); 624 ds.addPrimitive(newRelation); 625 } 626 for (Relation r : relations) { 627 Relation newRelation = (Relation)primitivesMap.get(r); 628 List<RelationMember> newMembers = new ArrayList<RelationMember>(); 629 for (RelationMember rm: r.getMembers()) { 630 newMembers.add(new RelationMember(rm.getRole(), primitivesMap.get(rm.getMember()))); 631 } 632 newRelation.setMembers(newMembers); 633 } 634 for (DataSource source : dataSources) { 635 ds.dataSources.add(new DataSource(source.bounds, source.origin)); 636 } 637 ds.version = version; 638 return ds; 639 } finally { 640 getReadLock().unlock(); 641 } 600 642 } 601 643 … … 663 705 } 664 706 665 pr otectedvoid deleteWay(Way way) {707 private void deleteWay(Way way) { 666 708 way.setNodes(null); 667 709 way.setDeleted(true); … … 674 716 */ 675 717 public void unlinkNodeFromWays(Node node) { 676 for (Way way: ways) { 677 List<Node> nodes = way.getNodes(); 678 if (nodes.remove(node)) { 679 if (nodes.size() < 2) { 680 deleteWay(way); 681 } else { 682 way.setNodes(nodes); 718 beginUpdate(); 719 try { 720 for (Way way: ways) { 721 List<Node> nodes = way.getNodes(); 722 if (nodes.remove(node)) { 723 if (nodes.size() < 2) { 724 deleteWay(way); 725 } else { 726 way.setNodes(nodes); 727 } 683 728 } 684 729 } 730 } finally { 731 endUpdate(); 685 732 } 686 733 } … … 692 739 */ 693 740 public void unlinkPrimitiveFromRelations(OsmPrimitive primitive) { 694 for (Relation relation : relations) { 695 List<RelationMember> members = relation.getMembers(); 696 697 Iterator<RelationMember> it = members.iterator(); 698 boolean removed = false; 699 while(it.hasNext()) { 700 RelationMember member = it.next(); 701 if (member.getMember().equals(primitive)) { 702 it.remove(); 703 removed = true; 741 beginUpdate(); 742 try { 743 for (Relation relation : relations) { 744 List<RelationMember> members = relation.getMembers(); 745 746 Iterator<RelationMember> it = members.iterator(); 747 boolean removed = false; 748 while(it.hasNext()) { 749 RelationMember member = it.next(); 750 if (member.getMember().equals(primitive)) { 751 it.remove(); 752 removed = true; 753 } 704 754 } 705 } 706 707 if (removed) { 708 relation.setMembers(members); 709 } 755 756 if (removed) { 757 relation.setMembers(members); 758 } 759 } 760 } finally { 761 endUpdate(); 710 762 } 711 763 } … … 718 770 */ 719 771 public void unlinkReferencesToPrimitive(OsmPrimitive referencedPrimitive) { 720 if (referencedPrimitive instanceof Node) { 721 unlinkNodeFromWays((Node)referencedPrimitive); 722 unlinkPrimitiveFromRelations(referencedPrimitive); 723 } else { 724 unlinkPrimitiveFromRelations(referencedPrimitive); 772 beginUpdate(); 773 try { 774 if (referencedPrimitive instanceof Node) { 775 unlinkNodeFromWays((Node)referencedPrimitive); 776 unlinkPrimitiveFromRelations(referencedPrimitive); 777 } else { 778 unlinkPrimitiveFromRelations(referencedPrimitive); 779 } 780 } finally { 781 endUpdate(); 725 782 } 726 783 } … … 804 861 */ 805 862 public void beginUpdate() { 863 lock.writeLock().lock(); 806 864 updateCount++; 807 865 } … … 814 872 updateCount--; 815 873 if (updateCount == 0) { 816 fireDataChanged(); 817 } 874 List<AbstractDatasetChangedEvent> eventsCopy = new ArrayList<AbstractDatasetChangedEvent>(cachedEvents); 875 cachedEvents.clear(); 876 lock.writeLock().unlock(); 877 878 if (!eventsCopy.isEmpty()) { 879 lock.readLock().lock(); 880 try { 881 if (eventsCopy.size() < MAX_SINGLE_EVENTS) { 882 for (AbstractDatasetChangedEvent event: eventsCopy) { 883 fireEventToListeners(event); 884 } 885 } else if (eventsCopy.size() == MAX_EVENTS) { 886 fireEventToListeners(new DataChangedEvent(this)); 887 } else { 888 fireEventToListeners(new DataChangedEvent(this, eventsCopy)); 889 } 890 } finally { 891 lock.readLock().unlock(); 892 } 893 } 894 } else { 895 lock.writeLock().unlock(); 896 } 897 818 898 } else 819 899 throw new AssertionError("endUpdate called without beginUpdate"); 820 900 } 821 901 902 private void fireEventToListeners(AbstractDatasetChangedEvent event) { 903 for (DataSetListener listener: listeners) { 904 event.fire(listener); 905 } 906 } 907 822 908 private void fireEvent(AbstractDatasetChangedEvent event) { 823 if (updateCount == 0) { 824 for (DataSetListener dsl : listeners) { 825 event.fire(dsl); 826 } 827 } 828 } 829 830 private void fireDataChanged() { 831 fireEvent(new DataChangedEvent(this)); 909 if (updateCount == 0) 910 throw new AssertionError("dataset events can be fired only when dataset is locked"); 911 if (cachedEvents.size() < MAX_EVENTS) { 912 cachedEvents.add(event); 913 } 832 914 } 833 915 … … 868 950 869 951 public void clenupDeletedPrimitives() { 870 if (cleanupDeleted(nodes.iterator()) 871 | cleanupDeleted(ways.iterator()) 872 | cleanupDeleted(relations.iterator())) { 873 fireSelectionChanged(); 952 beginUpdate(); 953 try { 954 if (cleanupDeleted(nodes.iterator()) 955 | cleanupDeleted(ways.iterator()) 956 | cleanupDeleted(relations.iterator())) { 957 fireSelectionChanged(); 958 } 959 } finally { 960 endUpdate(); 874 961 } 875 962 } … … 896 983 */ 897 984 public void clear() { 898 clearSelection(); 899 for (OsmPrimitive primitive:allPrimitives) { 900 primitive.setDataset(null); 901 } 902 nodes.clear(); 903 ways.clear(); 904 relations.clear(); 905 allPrimitives.clear(); 985 beginUpdate(); 986 try { 987 clearSelection(); 988 for (OsmPrimitive primitive:allPrimitives) { 989 primitive.setDataset(null); 990 } 991 nodes.clear(); 992 ways.clear(); 993 relations.clear(); 994 allPrimitives.clear(); 995 } finally { 996 endUpdate(); 997 } 906 998 } 907 999 }
Note:
See TracChangeset
for help on using the changeset viewer.