- Timestamp:
- 2009-11-08T13:38:44+01:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
r2402 r2407 543 543 544 544 newSelection.add(n); 545 ds.setSelected(n);546 545 } else if (!newNode) { 547 546 title = tr("Connect existing way to node"); -
trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
r2357 r2407 39 39 this.regexSearch = regexSearch; 40 40 this.tokenizer = tokenizer; 41 childBackRefs = new CollectBackReferencesVisitor( Main.main.getCurrentDataSet());41 childBackRefs = new CollectBackReferencesVisitor(true); 42 42 } 43 43 … … 230 230 231 231 switch (mode) { 232 case NONE: 233 return false; 234 case MISSING_KEY: 235 return osm.get(key) == null; 236 case ANY: 237 return true; 238 case ANY_VALUE: 239 return osm.get(key) != null; 240 case ANY_KEY: 241 for (String v:osm.getKeys().values()) { 242 if (v.equals(value)) 232 case NONE: 233 return false; 234 case MISSING_KEY: 235 return osm.get(key) == null; 236 case ANY: 237 return true; 238 case ANY_VALUE: 239 return osm.get(key) != null; 240 case ANY_KEY: 241 for (String v:osm.getKeys().values()) { 242 if (v.equals(value)) 243 return true; 244 } 245 return false; 246 case EXACT: 247 return value.equals(osm.get(key)); 248 case ANY_KEY_REGEXP: 249 for (String v:osm.getKeys().values()) { 250 if (valuePattern.matcher(v).matches()) 251 return true; 252 } 253 return false; 254 case ANY_VALUE_REGEXP: 255 case EXACT_REGEXP: 256 for (Entry<String, String> entry:osm.entrySet()) { 257 if (keyPattern.matcher(entry.getKey()).matches()) { 258 if (mode == Mode.ANY_VALUE_REGEXP 259 || valuePattern.matcher(entry.getValue()).matches()) 243 260 return true; 244 261 } 245 return false; 246 case EXACT: 247 return value.equals(osm.get(key)); 248 case ANY_KEY_REGEXP: 249 for (String v:osm.getKeys().values()) { 250 if (valuePattern.matcher(v).matches()) 251 return true; 252 } 253 return false; 254 case ANY_VALUE_REGEXP: 255 case EXACT_REGEXP: 256 for (Entry<String, String> entry:osm.entrySet()) { 257 if (keyPattern.matcher(entry.getKey()).matches()) { 258 if (mode == Mode.ANY_VALUE_REGEXP 259 || valuePattern.matcher(entry.getValue()).matches()) 260 return true; 261 } 262 } 263 return false; 264 case MISSING_KEY_REGEXP: 265 for (String k:osm.keySet()) { 266 if (keyPattern.matcher(k).matches()) 267 return false; 268 } 269 return true; 262 } 263 return false; 264 case MISSING_KEY_REGEXP: 265 for (String k:osm.keySet()) { 266 if (keyPattern.matcher(k).matches()) 267 return false; 268 } 269 return true; 270 270 } 271 271 throw new AssertionError("Missed state"); -
trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
r2405 r2407 147 147 * 148 148 * @return DataSet this primitive is part of. 149 * @throws DataIntegrityProblemException when primitive is not part of any dataset150 149 */ 151 150 public DataSet getDataSet() { 151 return dataSet; 152 } 153 154 /** 155 * Throws exception if primitive is not part of the dataset 156 */ 157 public void checkDataset() { 152 158 if (dataSet == null) 153 throw new DataIntegrityProblemException("Primitive must be part of the dataset"); 154 return dataSet; 159 throw new DataIntegrityProblemException("Primitive must be part of the dataset: " + toString()); 155 160 } 156 161 … … 648 653 return keys.keySet(); 649 654 } 655 656 657 /*------------ 658 * Referrers 659 ------------*/ 660 661 private Object referrers; 662 663 664 /** 665 * Add new referrer. If referrer is already included then no action is taken 666 * @param referrer 667 */ 668 protected void addReferrer(OsmPrimitive referrer) { 669 // Based on methods from josm-ng 670 if (referrers == null) { 671 referrers = referrer; 672 } else if (referrers instanceof OsmPrimitive) { 673 if (referrers != referrer) { 674 referrers = new OsmPrimitive[] { (OsmPrimitive)referrers, referrer }; 675 } 676 } else { 677 for (OsmPrimitive primitive:(OsmPrimitive[])referrers) { 678 if (primitive == referrer) 679 return; 680 } 681 OsmPrimitive[] orig = (OsmPrimitive[])referrers; 682 OsmPrimitive[] bigger = new OsmPrimitive[orig.length+1]; 683 System.arraycopy(orig, 0, bigger, 0, orig.length); 684 bigger[orig.length] = referrer; 685 referrers = bigger; 686 } 687 } 688 689 /** 690 * Remove referrer. No action is taken if referrer is not registered 691 * @param referrer 692 */ 693 protected void removeReferrer(OsmPrimitive referrer) { 694 // Based on methods from josm-ng 695 if (referrers instanceof OsmPrimitive) { 696 if (referrers == referrer) { 697 referrers = null; 698 } 699 } else if (referrers instanceof OsmPrimitive[]) { 700 OsmPrimitive[] orig = (OsmPrimitive[])referrers; 701 int idx = -1; 702 for (int i=0; i<orig.length; i++) { 703 if (orig[i] == referrer) { 704 idx = i; 705 break; 706 } 707 } 708 if (idx == -1) 709 return; 710 711 if (orig.length == 2) { 712 referrers = orig[1-idx]; // idx is either 0 or 1, take the other 713 } else { // downsize the array 714 OsmPrimitive[] smaller = new OsmPrimitive[orig.length-1]; 715 System.arraycopy(orig, 0, smaller, 0, idx); 716 System.arraycopy(orig, idx+1, smaller, idx, smaller.length-idx); 717 referrers = smaller; 718 } 719 } 720 } 721 /** 722 * Find primitives that reference this primitive. Returns only primitives that are included in the same 723 * dataset as this primitive. <br> 724 * 725 * For example following code will add wnew as referer to all nodes of existingWay, but this method will 726 * not return wnew because it's not part of the dataset <br> 727 * 728 * <code>Way wnew = new Way(existingWay)</code> 729 * 730 * @return a collection of all primitives that reference this primitive. 731 */ 732 733 public final List<OsmPrimitive> getReferrers() { 734 checkDataset(); 735 // Method copied from OsmPrimitive in josm-ng 736 // Returns only referrers that are members of the same dataset (primitive can have some fake references, for example 737 // when way is cloned 738 if (referrers == null) 739 return Collections.emptyList(); 740 741 if (referrers instanceof OsmPrimitive) { 742 if (((OsmPrimitive)referrers).dataSet == dataSet) 743 return Collections.singletonList((OsmPrimitive)referrers); 744 else 745 return Collections.emptyList(); 746 } 747 748 List<OsmPrimitive> result = new ArrayList<OsmPrimitive>(); 749 for (OsmPrimitive o:(OsmPrimitive[])referrers) { 750 if (dataSet == o.dataSet) { 751 result.add(o); 752 } 753 } 754 755 return result; 756 } 757 650 758 651 759 /** -
trunk/src/org/openstreetmap/josm/data/osm/Relation.java
r2405 r2407 39 39 */ 40 40 public void setMembers(List<RelationMember> members) { 41 for (RelationMember rm:this.members) { 42 rm.getMember().removeReferrer(this); 43 } 44 41 45 this.members.clear(); 42 46 if (members != null) { 43 47 this.members.addAll(members); 44 48 } 49 for (RelationMember rm:this.members) { 50 rm.getMember().addReferrer(this); 51 } 52 45 53 } 46 54 … … 70 78 public void addMember(RelationMember member) { 71 79 members.add(member); 80 member.getMember().addReferrer(this); 72 81 } 73 82 … … 80 89 public void addMember(int index, RelationMember member) { 81 90 members.add(index, member); 91 member.getMember().addReferrer(this); 82 92 } 83 93 … … 90 100 */ 91 101 public RelationMember setMember(int index, RelationMember member) { 92 return members.set(index, member); 102 RelationMember result = members.set(index, member); 103 if (result.getMember() != member.getMember()) { 104 member.getMember().addReferrer(this); 105 result.getMember().removeReferrer(this); 106 } 107 return result; 93 108 } 94 109 … … 100 115 */ 101 116 public RelationMember removeMember(int index) { 102 return members.remove(index); 117 RelationMember result = members.remove(index); 118 for (RelationMember rm:members) { 119 // Do not remove referrer if this primitive is used in relation twice 120 if (rm.getMember() == result.getMember()) 121 return result; 122 } 123 result.getMember().removeReferrer(this); 124 return result; 103 125 } 104 126 … … 139 161 @Override public void cloneFrom(OsmPrimitive osm) { 140 162 super.cloneFrom(osm); 141 members.clear(); 142 // we must not add the members themselves, but instead 143 // add clones of the members 144 for (RelationMember em : ((Relation)osm).getMembers()) { 145 members.add(new RelationMember(em)); 146 } 163 // It's not necessary to clone members as RelationMember class is immutable 164 setMembers(((Relation)osm).getMembers()); 147 165 } 148 166 … … 236 254 } 237 255 } 256 primitive.removeReferrer(this); 238 257 members.removeAll(todelete); 239 258 } 259 260 @Override 261 public void setDeleted(boolean deleted) { 262 for (RelationMember rm:members) { 263 if (deleted) { 264 rm.getMember().removeReferrer(this); 265 } else { 266 rm.getMember().addReferrer(this); 267 } 268 } 269 super.setDeleted(deleted); 270 } 271 240 272 241 273 /** … … 255 287 } 256 288 members.removeAll(todelete); 289 for (OsmPrimitive primitive:primitives) { 290 primitive.removeReferrer(this); 291 } 257 292 } 258 293 -
trunk/src/org/openstreetmap/josm/data/osm/Way.java
r2405 r2407 45 45 */ 46 46 public void setNodes(List<Node> nodes) { 47 for (Node node:this.nodes) { 48 node.removeReferrer(this); 49 } 50 47 51 if (nodes == null) { 48 52 this.nodes = new Node[0]; … … 50 54 this.nodes = nodes.toArray(new Node[nodes.size()]); 51 55 } 56 for (Node node:this.nodes) { 57 node.addReferrer(this); 58 } 59 52 60 clearCached(); 53 61 } … … 194 202 super.cloneFrom(osm); 195 203 Way otherWay = (Way)osm; 196 nodes = new Node[otherWay.nodes.length]; 197 System.arraycopy(otherWay.nodes, 0, nodes, 0, otherWay.nodes.length); 204 setNodes(otherWay.getNodes()); 198 205 } 199 206 … … 229 236 i = copy.size(); 230 237 if (closed && i > 2) { 238 // TODO Should this be copy.addNode(firstNode)? 231 239 addNode(firstNode()); 232 240 } else if (i >= 2 && i <= 3 && copy.get(0) == copy.get(i-1)) { … … 257 265 throw new IllegalStateException(tr("Cannot add node {0} to incomplete way {1}.", n.getId(), getId())); 258 266 clearCached(); 267 n.addReferrer(this); 259 268 Node[] newNodes = new Node[nodes.length + 1]; 260 269 System.arraycopy(nodes, 0, newNodes, 0, nodes.length); … … 277 286 throw new IllegalStateException(tr("Cannot add node {0} to incomplete way {1}.", n.getId(), getId())); 278 287 clearCached(); 288 n.addReferrer(this); 279 289 Node[] newNodes = new Node[nodes.length + 1]; 280 290 System.arraycopy(nodes, 0, newNodes, 0, offs); … … 284 294 } 285 295 296 @Override 297 public void setDeleted(boolean deleted) { 298 for (Node n:nodes) { 299 if (deleted) { 300 n.removeReferrer(this); 301 } else { 302 n.addReferrer(this); 303 } 304 } 305 super.setDeleted(deleted); 306 } 307 308 286 309 public boolean isClosed() { 287 310 if (incomplete) return false; -
trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java
r2381 r2407 4 4 import java.util.Collection; 5 5 import java.util.HashSet; 6 import java.util.HashMap;7 import java.util.Map;8 6 9 7 import org.openstreetmap.josm.data.osm.DataSet; … … 11 9 import org.openstreetmap.josm.data.osm.OsmPrimitive; 12 10 import org.openstreetmap.josm.data.osm.Relation; 13 import org.openstreetmap.josm.data.osm.RelationMember;14 11 import org.openstreetmap.josm.data.osm.Way; 15 12 … … 23 20 public class CollectBackReferencesVisitor extends AbstractVisitor { 24 21 25 private final DataSet ds;26 22 private final boolean indirectRefs; 27 23 28 24 private Collection<OsmPrimitive> data = new HashSet<OsmPrimitive>(); 29 private Map<OsmPrimitive, Collection<OsmPrimitive>> lookupTable = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();30 25 31 26 32 27 /** 33 * Construct a back reference counter. 34 * has time complexity O(n) - so it is appropriate not to call it in cycle 35 * @param ds The dataset to operate on. 28 * @param ds This parameter is ignored 36 29 */ 37 30 public CollectBackReferencesVisitor(DataSet ds) { 38 this(ds,true);31 this(true); 39 32 } 40 33 41 34 /** 42 * Construct a back reference counter. 43 * has time complexity O(n) - so it is appropriate not to call it in cycle 44 * @param ds The dataset to operate on. 35 * @param ds This parameter is ignored 45 36 * @param indirectRefs Make also indirect references? 46 37 */ 47 38 public CollectBackReferencesVisitor(DataSet ds, boolean indirectRefs) { 48 this.ds = ds; 49 this.indirectRefs = indirectRefs; 50 if(ds != null) 51 makeLookupTable(); 39 this.indirectRefs = indirectRefs; 52 40 } 53 54 private void makeLookupTable() { 55 for (Way w : ds.getWays()) { 56 for (Node n : w.getNodes()) { 57 if (!lookupTable.containsKey(n)) lookupTable.put(n, new HashSet<OsmPrimitive>()); 58 lookupTable.get(n).add(w); 59 } 60 } 61 for (Relation r : ds.getRelations()) { 62 for (RelationMember m : r.getMembers()) { 63 OsmPrimitive o = m.getMember(); 64 if (!lookupTable.containsKey(o)) lookupTable.put(o, new HashSet<OsmPrimitive>()); 65 lookupTable.get(o).add(r); 66 } 67 } 41 42 public CollectBackReferencesVisitor(boolean indirectRefs) { 43 this.indirectRefs = indirectRefs; 68 44 } 45 69 46 70 47 /** … … 72 49 */ 73 50 public Collection<OsmPrimitive> getData(){ 74 return data;51 return data; 75 52 } 76 53 77 54 /** 78 * Initialize data before associated visit calls 55 * Initialize data before associated visit calls 79 56 */ 80 57 public void initialize(){ 81 data = new HashSet<OsmPrimitive>();58 data = new HashSet<OsmPrimitive>(); 82 59 } 83 60 84 61 public void visit(OsmPrimitive o) { 85 if(lookupTable.containsKey(o)){ 86 Collection<OsmPrimitive> c = lookupTable.get(o); 87 Collection<OsmPrimitive> oldData = new HashSet<OsmPrimitive>(data); 88 data.addAll(c); 89 if(indirectRefs) 90 for(OsmPrimitive oo : c) 91 if(!oldData.contains(oo)) 92 visit(oo); 93 } 62 Collection<OsmPrimitive> c = o.getReferrers(); 63 Collection<OsmPrimitive> oldData = new HashSet<OsmPrimitive>(data); 64 data.addAll(c); 65 if(indirectRefs) { 66 for(OsmPrimitive oo : c) 67 if(!oldData.contains(oo)) { 68 visit(oo); 69 } 70 } 71 94 72 } 95 73 96 74 public void visit(Node n) { 97 visit((OsmPrimitive)n);75 visit((OsmPrimitive)n); 98 76 } 99 77 100 78 public void visit(Way w) { 101 visit((OsmPrimitive)w);79 visit((OsmPrimitive)w); 102 80 } 103 81 104 82 public void visit(Relation r) { 105 visit((OsmPrimitive)r);83 visit((OsmPrimitive)r); 106 84 } 107 85 }
Note:
See TracChangeset
for help on using the changeset viewer.