- Timestamp:
- 2009-10-24T21:22:49+02:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 2 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/Main.java
r2274 r2305 39 39 import org.openstreetmap.josm.data.coor.CoordinateFormat; 40 40 import org.openstreetmap.josm.data.osm.DataSet; 41 import org.openstreetmap.josm.data. projection.Mercator;41 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 42 42 import org.openstreetmap.josm.data.projection.Projection; 43 43 import org.openstreetmap.josm.gui.GettingStarted; … … 89 89 * The global paste buffer. 90 90 */ 91 public static DataSet pasteBuffer = new DataSet();91 public static PrimitiveDeepCopy pasteBuffer = new PrimitiveDeepCopy(); 92 92 public static Layer pasteSource; 93 93 /** … … 377 377 /** 378 378 * Run any cleanup operation before exit 379 * 379 * 380 380 */ 381 381 public static void cleanupBeforeExit() { -
trunk/src/org/openstreetmap/josm/actions/CopyAction.java
r2283 r2305 7 7 import java.awt.event.ActionEvent; 8 8 import java.awt.event.KeyEvent; 9 import java.util.ArrayList;10 9 import java.util.Collection; 11 import java.util.HashMap;12 10 import java.util.LinkedList; 13 import java.util.List;14 11 15 12 import javax.swing.JOptionPane; 16 13 17 14 import org.openstreetmap.josm.Main; 18 import org.openstreetmap.josm.data.osm.DataSet;19 import org.openstreetmap.josm.data.osm.Node;20 15 import org.openstreetmap.josm.data.osm.OsmPrimitive; 21 import org.openstreetmap.josm.data.osm.Relation;22 import org.openstreetmap.josm.data.osm.RelationMember;23 import org.openstreetmap.josm.data.osm.Way;24 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;25 16 import org.openstreetmap.josm.tools.Shortcut; 26 17 … … 43 34 if(isEmptySelection()) return; 44 35 45 Main.pasteBuffer = copyData();36 Main.pasteBuffer.makeCopy(getCurrentDataSet().getSelected()); 46 37 Main.pasteSource = getEditLayer(); 47 38 Main.main.menu.paste.setEnabled(true); /* now we have a paste buffer we can make paste available */ … … 50 41 a.pasteBufferChanged(Main.pasteBuffer); 51 42 } 52 }53 54 public DataSet copyData() {55 /* New pasteBuffer - will be assigned to the global one at the end */56 final DataSet pasteBuffer = new DataSet();57 final HashMap<OsmPrimitive,OsmPrimitive> map = new HashMap<OsmPrimitive,OsmPrimitive>();58 /* temporarily maps old nodes to new so we can do a true deep copy */59 60 if(isEmptySelection()) return pasteBuffer;61 62 /* scan the selected objects, mapping them to copies; when copying a way or relation,63 * the copy references the copies of their child objects */64 new AbstractVisitor() {65 public void visit(Node n) {66 /* check if already in pasteBuffer - e.g. two ways are selected which share a node;67 * or a way and a node in that way is selected, we'll see it twice, once via the68 * way and once directly; and so on. */69 if (map.containsKey(n))70 return;71 Node nnew = new Node(n);72 map.put(n, nnew);73 pasteBuffer.addPrimitive(nnew);74 }75 public void visit(Way w) {76 /* check if already in pasteBuffer - could have come from a relation, and directly etc. */77 if (map.containsKey(w))78 return;79 Way wnew = new Way();80 wnew.cloneFrom(w);81 map.put(w, wnew);82 List<Node> nodes = new ArrayList<Node>();83 for (Node n : w.getNodes()) {84 if (! map.containsKey(n)) {85 n.visit(this);86 }87 nodes.add((Node)map.get(n));88 }89 wnew.setNodes(nodes);90 pasteBuffer.addPrimitive(wnew);91 }92 public void visit(Relation e) {93 if (map.containsKey(e))94 return;95 Relation enew = new Relation(e);96 map.put(e, enew);97 List<RelationMember> members = new ArrayList<RelationMember>();98 for (RelationMember m : e.getMembers()) {99 if (! map.containsKey(m.getMember())) {100 m.getMember().visit(this);101 }102 RelationMember mnew = new RelationMember(m.getRole(), map.get(m.getMember()));103 members.add(mnew);104 }105 enew.setMembers(members);106 pasteBuffer.addPrimitive(enew);107 }108 public void visitAll() {109 for (OsmPrimitive osm : getCurrentDataSet().getSelected()) {110 osm.visit(this);111 }112 }113 }.visitAll();114 115 return pasteBuffer;116 43 } 117 44 -
trunk/src/org/openstreetmap/josm/actions/DuplicateAction.java
r2256 r2305 10 10 11 11 import org.openstreetmap.josm.data.osm.OsmPrimitive; 12 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 12 13 import org.openstreetmap.josm.tools.Shortcut; 13 14 … … 21 22 22 23 public void actionPerformed(ActionEvent e) { 23 new PasteAction().pasteData(new CopyAction().copyData(), getEditLayer(), e);24 new PasteAction().pasteData(new PrimitiveDeepCopy(getCurrentDataSet().getSelected()), getEditLayer(), e); 24 25 } 25 26 -
trunk/src/org/openstreetmap/josm/actions/JosmAction.java
r2260 r2305 13 13 import org.openstreetmap.josm.data.osm.DataSet; 14 14 import org.openstreetmap.josm.data.osm.OsmPrimitive; 15 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 15 16 import org.openstreetmap.josm.gui.layer.Layer; 16 17 import org.openstreetmap.josm.gui.layer.OsmDataLayer; … … 22 23 /** 23 24 * Base class helper for all Actions in JOSM. Just to make the life easier. 24 * 25 * 25 26 * A JosmAction is a {@see LayerChangeListener} and a {@see SelectionChangedListener}. Upon 26 27 * a layer change event or a selection change event it invokes {@see #updateEnabled()}. … … 28 29 * of a JosmAction depending on the {@see #getCurrentDataSet()} and the current layers 29 30 * (see also {@see #getEditLayer()}). 30 * 31 * 31 32 * destroy() from interface Destroyable is called e.g. for MapModes, when the last layer has 32 33 * been removed and so the mapframe will be destroyed. For other JosmActions, destroy() may never … … 105 106 * needs to be overridden to be useful 106 107 */ 107 public void pasteBufferChanged( DataSetnewPasteBuffer) {108 public void pasteBufferChanged(PrimitiveDeepCopy newPasteBuffer) { 108 109 return; 109 110 } … … 126 127 /** 127 128 * Replies the current edit layer 128 * 129 * 129 130 * @return the current edit layer. null, if no edit layer exists 130 131 */ … … 135 136 /** 136 137 * Replies the current dataset 137 * 138 * 138 139 * @return the current dataset. null, if no current dataset exists 139 140 */ … … 155 156 * Override in subclasses to init the enabled state of an action when it is 156 157 * created. Default behaviour is to call {@see #updateEnabledState()} 157 * 158 * 158 159 * @see #updateEnabledState() 159 160 * @see #updateEnabledState(Collection) … … 166 167 * Override in subclasses to update the enabled state of the action when 167 168 * something in the JOSM state changes, i.e. when a layer is removed or added. 168 * 169 * 169 170 * See {@see #updateEnabledState(Collection)} to respond to changes in the collection 170 171 * of selected primitives. 171 * 172 * 172 173 * Default behavior is empty. 173 * 174 * 174 175 * @see #updateEnabledState(Collection) 175 176 * @see #initEnabledState() … … 183 184 * new selection. Avoid calling getCurrentDataSet().getSelected() because this 184 185 * loops over the complete data set. 185 * 186 * 186 187 * @param selection the collection of selected primitives 187 * 188 * 188 189 * @see #updateEnabledState() 189 190 * @see #initEnabledState() -
trunk/src/org/openstreetmap/josm/actions/MoveAction.java
r2256 r2305 81 81 disty = 0; 82 82 distx = -distx; 83 break; 83 84 default: 84 85 disty = 0; -
trunk/src/org/openstreetmap/josm/actions/PasteAction.java
r2070 r2305 8 8 import java.awt.event.KeyEvent; 9 9 import java.util.ArrayList; 10 import java.util.Collection;11 10 import java.util.HashMap; 12 import java.util.LinkedList;13 11 import java.util.List; 12 import java.util.ListIterator; 13 import java.util.Map; 14 14 15 15 import org.openstreetmap.josm.Main; 16 import org.openstreetmap.josm.command.AddCommand; 17 import org.openstreetmap.josm.command.Command; 18 import org.openstreetmap.josm.command.SequenceCommand; 16 import org.openstreetmap.josm.command.AddPrimitivesCommand; 19 17 import org.openstreetmap.josm.data.coor.EastNorth; 20 import org.openstreetmap.josm.data.osm. DataSet;21 import org.openstreetmap.josm.data.osm. Node;22 import org.openstreetmap.josm.data.osm. OsmPrimitive;23 import org.openstreetmap.josm.data.osm.Relation ;24 import org.openstreetmap.josm.data.osm.RelationMember ;25 import org.openstreetmap.josm.data.osm.Way ;18 import org.openstreetmap.josm.data.osm.NodeData; 19 import org.openstreetmap.josm.data.osm.PrimitiveData; 20 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 21 import org.openstreetmap.josm.data.osm.RelationData; 22 import org.openstreetmap.josm.data.osm.RelationMemberData; 23 import org.openstreetmap.josm.data.osm.WayData; 26 24 import org.openstreetmap.josm.gui.layer.Layer; 27 25 import org.openstreetmap.josm.tools.Shortcut; … … 40 38 } 41 39 42 public void pasteData( DataSetpasteBuffer, Layer source, ActionEvent e) {40 public void pasteData(PrimitiveDeepCopy pasteBuffer, Layer source, ActionEvent e) { 43 41 /* Find the middle of the pasteBuffer area */ 44 42 double maxEast = -1E100, minEast = 1E100, maxNorth = -1E100, minNorth = 1E100; 45 for (Node n : pasteBuffer.nodes) { 46 double east = n.getEastNorth().east(); 47 double north = n.getEastNorth().north(); 48 if (east > maxEast) { maxEast = east; } 49 if (east < minEast) { minEast = east; } 50 if (north > maxNorth) { maxNorth = north; } 51 if (north < minNorth) { minNorth = north; } 43 for (PrimitiveData data : pasteBuffer.getAll()) { 44 if (data instanceof NodeData) { 45 NodeData n = (NodeData)data; 46 double east = n.getEastNorth().east(); 47 double north = n.getEastNorth().north(); 48 if (east > maxEast) { maxEast = east; } 49 if (east < minEast) { minEast = east; } 50 if (north > maxNorth) { maxNorth = north; } 51 if (north < minNorth) { minNorth = north; } 52 } 52 53 } 53 54 … … 63 64 double offsetNorth = mPosition.north() - (maxNorth + minNorth)/2.0; 64 65 65 HashMap<OsmPrimitive,OsmPrimitive> map = new HashMap<OsmPrimitive,OsmPrimitive>();66 /* temporarily maps old nodes to new so we can do a true deep copy */67 66 68 /* do the deep copy of the paste buffer contents, leaving the pasteBuffer unchanged */ 69 for (Node n : pasteBuffer.nodes) { 70 Node nnew = new Node(n); 71 nnew.clearOsmId(); 72 if (Main.map.mapView.getEditLayer() == source) { 73 nnew.setEastNorth(nnew.getEastNorth().add(offsetEast, offsetNorth)); 74 } 75 map.put(n, nnew); 67 68 // Make a copy of pasteBuffer and map from old id to copied data id 69 List<PrimitiveData> bufferCopy = new ArrayList<PrimitiveData>(); 70 Map<Long, Long> newIds = new HashMap<Long, Long>(); 71 for (PrimitiveData data:pasteBuffer.getAll()) { 72 PrimitiveData copy = data.makeCopy(); 73 copy.clearOsmId(); 74 newIds.put(data.getId(), copy.getId()); 75 bufferCopy.add(copy); 76 76 } 77 for (Way w : pasteBuffer.ways) { 78 Way wnew = new Way(); 79 wnew.cloneFrom(w); 80 wnew.clearOsmId(); 81 /* make sure we reference the new nodes corresponding to the old ones */ 82 List<Node> nodes = new ArrayList<Node>(); 83 for (Node n : w.getNodes()) { 84 nodes.add((Node)map.get(n)); 85 } 86 wnew.setNodes(nodes); 87 map.put(w, wnew); 88 } 89 for (Relation r : pasteBuffer.relations) { 90 Relation rnew = new Relation(r); 91 r.clearOsmId(); 92 List<RelationMember> members = new ArrayList<RelationMember>(); 93 for (RelationMember m : r.getMembers()) { 94 OsmPrimitive mo = map.get(m.getMember()); 95 if(mo != null) /* FIXME - This only prevents illegal data, but kills the relation */ 96 { 97 RelationMember mnew = new RelationMember(m.getRole(), map.get(m.getMember())); 98 members.add(mnew); 77 78 // Update references in copied buffer 79 for (PrimitiveData data:bufferCopy) { 80 if (data instanceof NodeData) { 81 NodeData nodeData = (NodeData)data; 82 if (Main.map.mapView.getEditLayer() == source) { 83 nodeData.setEastNorth(nodeData.getEastNorth().add(offsetEast, offsetNorth)); 84 } 85 } else if (data instanceof WayData) { 86 ListIterator<Long> it = ((WayData)data).getNodes().listIterator(); 87 while (it.hasNext()) { 88 it.set(newIds.get(it.next())); 89 } 90 } else if (data instanceof RelationData) { 91 ListIterator<RelationMemberData> it = ((RelationData)data).getMembers().listIterator(); 92 while (it.hasNext()) { 93 RelationMemberData member = it.next(); 94 it.set(new RelationMemberData(member.getRole(), member.getMemberType(), newIds.get(member.getMemberId()))); 99 95 } 100 96 } 101 rnew.setMembers(members);102 map.put(r, rnew);103 97 } 104 98 105 /* Now execute the commands to add the dupicated contents of the paste buffer to the map */ 106 Collection<OsmPrimitive> osms = map.values(); 107 Collection<Command> clist = new LinkedList<Command>(); 108 for (OsmPrimitive osm : osms) { 109 clist.add(new AddCommand(osm)); 110 } 99 /* Now execute the commands to add the duplicated contents of the paste buffer to the map */ 111 100 112 Main.main.undoRedo.add(new SequenceCommand(tr("Paste"), clist));113 getCurrentDataSet().setSelected(osms);101 Main.main.undoRedo.add(new AddPrimitivesCommand(bufferCopy)); 102 //getCurrentDataSet().setSelected(osms); 114 103 Main.map.mapView.repaint(); 115 104 } … … 121 110 return; 122 111 } 123 setEnabled( 124 !Main.pasteBuffer.nodes.isEmpty() 125 || !Main.pasteBuffer.ways.isEmpty() 126 || !Main.pasteBuffer.relations.isEmpty() 127 ); 112 setEnabled(!Main.pasteBuffer.isEmpty()); 128 113 } 129 114 } -
trunk/src/org/openstreetmap/josm/actions/PasteTagsAction.java
r2256 r2305 18 18 import org.openstreetmap.josm.command.Command; 19 19 import org.openstreetmap.josm.command.SequenceCommand; 20 import org.openstreetmap.josm.data.osm.DataSet;21 import org.openstreetmap.josm.data.osm.Node;22 20 import org.openstreetmap.josm.data.osm.OsmPrimitive; 23 21 import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 24 import org.openstreetmap.josm.data.osm.Relation; 22 import org.openstreetmap.josm.data.osm.PrimitiveData; 23 import org.openstreetmap.josm.data.osm.PrimitiveDeepCopy; 25 24 import org.openstreetmap.josm.data.osm.TagCollection; 26 import org.openstreetmap.josm.data.osm.Way;27 25 import org.openstreetmap.josm.gui.conflict.tags.PasteTagsConflictResolverDialog; 28 26 import org.openstreetmap.josm.tools.Shortcut; … … 37 35 } 38 36 39 static private List<Class<? extends OsmPrimitive>> osmPrimitiveClasses; 40 static { 41 osmPrimitiveClasses = new ArrayList<Class<? extends OsmPrimitive>>(); 42 osmPrimitiveClasses.add(Node.class); 43 osmPrimitiveClasses.add(Way.class); 44 osmPrimitiveClasses.add(Relation.class); 45 } 46 47 /** 48 * Replies true if the source for tag pasting is heterogeneous, i.e. if it doesn't consist of 49 * {@see OsmPrimitive}s of exactly one type 50 * 51 * @return 52 */ 53 protected boolean isHeteogeneousSource() { 54 int count = 0; 55 count = !getSourcePrimitivesByType(Node.class).isEmpty() ? count + 1 : count; 56 count = !getSourcePrimitivesByType(Way.class).isEmpty() ? count + 1 : count; 57 count = !getSourcePrimitivesByType(Relation.class).isEmpty() ? count + 1 : count; 58 return count > 1; 59 } 60 61 /** 62 * Replies all primitives of type <code>type</code> in the current selection. 63 * 64 * @param <T> 65 * @param type the type 66 * @return all primitives of type <code>type</code> in the current selection. 67 */ 68 protected <T extends OsmPrimitive> Collection<? extends OsmPrimitive> getSourcePrimitivesByType(Class<T> type) { 69 return OsmPrimitive.getFilteredList(Main.pasteBuffer.getSelected(), type); 70 } 71 72 /** 73 * Replies the collection of tags for all primitives of type <code>type</code> in the current 74 * selection 75 * 76 * @param <T> 77 * @param type the type 78 * @return the collection of tags for all primitives of type <code>type</code> in the current 79 * selection 80 */ 81 protected <T extends OsmPrimitive> TagCollection getSourceTagsByType(Class<T> type) { 82 return TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 83 } 84 85 /** 86 * Replies true if there is at least one tag in the current selection for primitives of 87 * type <code>type</code> 88 * 89 * @param <T> 90 * @param type the type 91 * @return true if there is at least one tag in the current selection for primitives of 92 * type <code>type</code> 93 */ 94 protected <T extends OsmPrimitive> boolean hasSourceTagsByType(Class<T> type) { 95 return ! getSourceTagsByType(type).isEmpty(); 96 } 97 98 protected Command buildChangeCommand(Collection<? extends OsmPrimitive> selection, TagCollection tc) { 99 List<Command> commands = new ArrayList<Command>(); 100 for (String key : tc.getKeys()) { 101 String value = tc.getValues(key).iterator().next(); 102 value = value.equals("") ? null : value; 103 commands.add(new ChangePropertyCommand(selection,key,value)); 104 } 105 if (!commands.isEmpty()) { 106 String title1 = trn("Pasting {0} tag", "Pasting {0} tags", tc.getKeys().size(), tc.getKeys().size()); 107 String title2 = trn("to {0} primitive", "to {0} primtives", selection.size(), selection.size()); 108 return new SequenceCommand( 109 title1 + " " + title2, 110 commands 111 ); 112 } 113 return null; 114 } 115 116 protected Map<OsmPrimitiveType, Integer> getSourceStatistics() { 117 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 118 for (Class<? extends OsmPrimitive> type: osmPrimitiveClasses) { 119 if (!getSourceTagsByType(type).isEmpty()) { 120 ret.put(OsmPrimitiveType.from(type), getSourcePrimitivesByType(type).size()); 121 } 122 } 123 return ret; 124 } 125 126 protected Map<OsmPrimitiveType, Integer> getTargetStatistics() { 127 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 128 for (Class<? extends OsmPrimitive> type: osmPrimitiveClasses) { 129 int count = OsmPrimitive.getFilteredList(getEditLayer().data.getSelected(), type).size(); 130 if (count > 0) { 131 ret.put(OsmPrimitiveType.from(type), count); 132 } 133 } 134 return ret; 135 } 136 137 /** 138 * Pastes the tags from a homogeneous source (i.e. the {@see Main#pasteBuffer}s selection consisting 139 * of one type of {@see OsmPrimitive}s only. 140 * 141 * Tags from a homogeneous source can be pasted to a heterogeneous target. All target primitives, 142 * regardless of their type, receive the same tags. 143 * 144 * @param targets the collection of target primitives 145 */ 146 protected void pasteFromHomogeneousSource(Collection<? extends OsmPrimitive> targets) { 147 TagCollection tc = null; 148 for (Class<? extends OsmPrimitive> type : osmPrimitiveClasses) { 149 TagCollection tc1 = getSourceTagsByType(type); 150 if (!tc1.isEmpty()) { 151 tc = tc1; 152 } 153 } 154 if (tc == null) 155 // no tags found to paste. Abort. 156 return; 157 158 if (!tc.isApplicableToPrimitive()) { 159 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 160 dialog.populate(tc, getSourceStatistics(), getTargetStatistics()); 161 dialog.setVisible(true); 162 if (dialog.isCanceled()) 37 public static class TagPaster { 38 39 private final Collection<PrimitiveData> source; 40 private final Collection<OsmPrimitive> target; 41 private final List<Command> commands = new ArrayList<Command>(); 42 43 public TagPaster(Collection<PrimitiveData> source, Collection<OsmPrimitive> target) { 44 this.source = source; 45 this.target = target; 46 } 47 48 /** 49 * Replies true if the source for tag pasting is heterogeneous, i.e. if it doesn't consist of 50 * {@see OsmPrimitive}s of exactly one type 51 * 52 * @return 53 */ 54 protected boolean isHeteogeneousSource() { 55 int count = 0; 56 count = !getSourcePrimitivesByType(OsmPrimitiveType.NODE).isEmpty() ? count + 1 : count; 57 count = !getSourcePrimitivesByType(OsmPrimitiveType.WAY).isEmpty() ? count + 1 : count; 58 count = !getSourcePrimitivesByType(OsmPrimitiveType.RELATION).isEmpty() ? count + 1 : count; 59 return count > 1; 60 } 61 62 /** 63 * Replies all primitives of type <code>type</code> in the current selection. 64 * 65 * @param <T> 66 * @param type the type 67 * @return all primitives of type <code>type</code> in the current selection. 68 */ 69 protected <T extends PrimitiveData> Collection<? extends PrimitiveData> getSourcePrimitivesByType(OsmPrimitiveType type) { 70 return PrimitiveData.getFilteredList(source, type); 71 } 72 73 /** 74 * Replies the collection of tags for all primitives of type <code>type</code> in the current 75 * selection 76 * 77 * @param <T> 78 * @param type the type 79 * @return the collection of tags for all primitives of type <code>type</code> in the current 80 * selection 81 */ 82 protected <T extends OsmPrimitive> TagCollection getSourceTagsByType(OsmPrimitiveType type) { 83 return TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 84 } 85 86 /** 87 * Replies true if there is at least one tag in the current selection for primitives of 88 * type <code>type</code> 89 * 90 * @param <T> 91 * @param type the type 92 * @return true if there is at least one tag in the current selection for primitives of 93 * type <code>type</code> 94 */ 95 protected <T extends OsmPrimitive> boolean hasSourceTagsByType(OsmPrimitiveType type) { 96 return ! getSourceTagsByType(type).isEmpty(); 97 } 98 99 protected Command buildChangeCommand(Collection<? extends OsmPrimitive> selection, TagCollection tc) { 100 List<Command> commands = new ArrayList<Command>(); 101 for (String key : tc.getKeys()) { 102 String value = tc.getValues(key).iterator().next(); 103 value = value.equals("") ? null : value; 104 commands.add(new ChangePropertyCommand(selection,key,value)); 105 } 106 if (!commands.isEmpty()) { 107 String title1 = trn("Pasting {0} tag", "Pasting {0} tags", tc.getKeys().size(), tc.getKeys().size()); 108 String title2 = trn("to {0} primitive", "to {0} primtives", selection.size(), selection.size()); 109 return new SequenceCommand( 110 title1 + " " + title2, 111 commands 112 ); 113 } 114 return null; 115 } 116 117 protected Map<OsmPrimitiveType, Integer> getSourceStatistics() { 118 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 119 for (OsmPrimitiveType type: OsmPrimitiveType.values()) { 120 if (!getSourceTagsByType(type).isEmpty()) { 121 ret.put(type, getSourcePrimitivesByType(type).size()); 122 } 123 } 124 return ret; 125 } 126 127 protected Map<OsmPrimitiveType, Integer> getTargetStatistics() { 128 HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>(); 129 for (OsmPrimitiveType type: OsmPrimitiveType.values()) { 130 int count = OsmPrimitive.getFilteredList(target, type.getOsmClass()).size(); 131 if (count > 0) { 132 ret.put(type, count); 133 } 134 } 135 return ret; 136 } 137 138 /** 139 * Pastes the tags from a homogeneous source (i.e. the {@see Main#pasteBuffer}s selection consisting 140 * of one type of {@see OsmPrimitive}s only. 141 * 142 * Tags from a homogeneous source can be pasted to a heterogeneous target. All target primitives, 143 * regardless of their type, receive the same tags. 144 * 145 * @param targets the collection of target primitives 146 */ 147 protected void pasteFromHomogeneousSource() { 148 TagCollection tc = null; 149 for (OsmPrimitiveType type : OsmPrimitiveType.values()) { 150 TagCollection tc1 = getSourceTagsByType(type); 151 if (!tc1.isEmpty()) { 152 tc = tc1; 153 } 154 } 155 if (tc == null) 156 // no tags found to paste. Abort. 163 157 return; 164 Command cmd = buildChangeCommand(targets, dialog.getResolution()); 165 Main.main.undoRedo.add(cmd);166 } else {167 // no conflicts in the source tags to resolve. Just apply the tags168 // to the target primitives169 //170 Command cmd = buildChangeCommand(targets, tc);171 Main.main.undoRedo.add(cmd);172 }173 }174 175 /**176 * Replies true if there is at least one primitive of type <code>type</code> in the collection177 * <code>selection</code>178 *179 * @param <T>180 * @param selection the collection of primitives181 * @param type the type to look for 182 * @return true if there is at least one primitive of type <code>type</code> in the collection183 * <code>selection</code>184 */185 protected <T extends OsmPrimitive> boolean hasTargetPrimitives(Collection<OsmPrimitive> selection, Class<T> type) {186 return !OsmPrimitive.getFilteredList(selection, type).isEmpty();187 }188 189 /**190 * Replies true if this a heterogeneous source can be pasted without conflict to targets191 *192 * @param targets the collection of target primitives193 * @return true if this a heterogeneous source can be pasted without conflicts to targets194 */195 protected boolean canPasteFromHeterogeneousSourceWithoutConflict(Collection<OsmPrimitive> targets) { 196 if (hasTargetPrimitives(targets, Node.class)) {197 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Node.class));198 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive())199 return false;200 }201 if (hasTargetPrimitives(targets, Way.class)) {202 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Way.class));203 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive())204 return false;205 }206 if (hasTargetPrimitives(targets, Relation.class)) {207 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(Relation.class));208 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive())209 return false;210 }211 return true;212 } 213 214 /**215 * Pastes the tags in the current selection of the paste buffer to a set of target216 * primitives.217 *218 * @param targets the collection of target primitives219 */220 protected void pasteFromHeterogeneousSource(Collection<OsmPrimitive> targets) {221 if (canPasteFromHeterogeneousSourceWithoutConflict(targets)) {222 if (hasSourceTagsByType(Node.class) && hasTargetPrimitives(targets, Node.class)) {223 Command cmd = buildChangeCommand(targets, getSourceTagsByType(Node.class));224 Main.main.undoRedo.add(cmd);225 }226 if (hasSourceTagsByType(Way.class) && hasTargetPrimitives(targets, Way.class)) {227 Command cmd = buildChangeCommand(targets, getSourceTagsByType(Way.class));228 Main.main.undoRedo.add(cmd);229 }230 if (hasSourceTagsByType(Relation.class) && hasTargetPrimitives(targets, Relation.class)) {231 Command cmd = buildChangeCommand(targets,getSourceTagsByType(Relation.class));232 Main.main.undoRedo.add(cmd);233 }234 } else {235 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent);236 dialog.populate(237 getSourceTagsByType(Node.class),238 getSourceTagsByType(Way.class),239 getSourceTagsByType(Relation.class),240 getSourceStatistics(),241 getTargetStatistics()242 );243 dialog.setVisible(true);244 if (dialog.isCanceled())245 return;246 if (hasSourceTagsByType(Node.class) && hasTargetPrimitives(targets, Node.class)) {247 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(targets, Node.class), dialog.getResolution(OsmPrimitiveType.NODE)); 248 Main.main.undoRedo.add(cmd);249 }250 if ( hasSourceTagsByType(Way.class) && hasTargetPrimitives(targets, Way.class)) {251 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(targets, Way.class), dialog.getResolution(OsmPrimitiveType.WAY));252 Main.main.undoRedo.add(cmd);253 }254 if (hasSourceTagsByType(Relation.class) && hasTargetPrimitives(targets, Relation.class)) {255 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(targets, Relation.class), dialog.getResolution(OsmPrimitiveType.RELATION));256 Main.main.undoRedo.add(cmd);257 } 258 259 } 158 159 if (!tc.isApplicableToPrimitive()) { 160 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 161 dialog.populate(tc, getSourceStatistics(), getTargetStatistics()); 162 dialog.setVisible(true); 163 if (dialog.isCanceled()) 164 return; 165 Command cmd = buildChangeCommand(target, dialog.getResolution()); 166 commands.add(cmd); 167 } else { 168 // no conflicts in the source tags to resolve. Just apply the tags 169 // to the target primitives 170 // 171 Command cmd = buildChangeCommand(target, tc); 172 commands.add(cmd); 173 } 174 } 175 176 /** 177 * Replies true if there is at least one primitive of type <code>type</code> in the collection 178 * <code>selection</code> 179 * 180 * @param <T> 181 * @param selection the collection of primitives 182 * @param type the type to look for 183 * @return true if there is at least one primitive of type <code>type</code> in the collection 184 * <code>selection</code> 185 */ 186 protected <T extends OsmPrimitive> boolean hasTargetPrimitives(Class<T> type) { 187 return !OsmPrimitive.getFilteredList(target, type).isEmpty(); 188 } 189 190 /** 191 * Replies true if this a heterogeneous source can be pasted without conflict to targets 192 * 193 * @param targets the collection of target primitives 194 * @return true if this a heterogeneous source can be pasted without conflicts to targets 195 */ 196 protected boolean canPasteFromHeterogeneousSourceWithoutConflict(Collection<OsmPrimitive> targets) { 197 for (OsmPrimitiveType type:OsmPrimitiveType.values()) { 198 if (hasTargetPrimitives(type.getOsmClass())) { 199 TagCollection tc = TagCollection.unionOfAllPrimitives(getSourcePrimitivesByType(type)); 200 if (!tc.isEmpty() && ! tc.isApplicableToPrimitive()) 201 return false; 202 } 203 } 204 return true; 205 } 206 207 /** 208 * Pastes the tags in the current selection of the paste buffer to a set of target 209 * primitives. 210 * 211 * @param targets the collection of target primitives 212 */ 213 protected void pasteFromHeterogeneousSource() { 214 if (canPasteFromHeterogeneousSourceWithoutConflict(target)) { 215 for (OsmPrimitiveType type:OsmPrimitiveType.values()) { 216 if (hasSourceTagsByType(type) && hasTargetPrimitives(type.getOsmClass())) { 217 Command cmd = buildChangeCommand(target, getSourceTagsByType(type)); 218 commands.add(cmd); 219 } 220 } 221 } else { 222 PasteTagsConflictResolverDialog dialog = new PasteTagsConflictResolverDialog(Main.parent); 223 dialog.populate( 224 getSourceTagsByType(OsmPrimitiveType.NODE), 225 getSourceTagsByType(OsmPrimitiveType.WAY), 226 getSourceTagsByType(OsmPrimitiveType.RELATION), 227 getSourceStatistics(), 228 getTargetStatistics() 229 ); 230 dialog.setVisible(true); 231 if (dialog.isCanceled()) 232 return; 233 for (OsmPrimitiveType type:OsmPrimitiveType.values()) { 234 if (hasSourceTagsByType(type) && hasTargetPrimitives(type.getOsmClass())) { 235 Command cmd = buildChangeCommand(OsmPrimitive.getFilteredList(target, type.getOsmClass()), dialog.getResolution(type)); 236 commands.add(cmd); 237 } 238 } 239 } 240 } 241 242 public List<Command> execute() { 243 commands.clear(); 244 if (isHeteogeneousSource()) { 245 pasteFromHeterogeneousSource(); 246 } else { 247 pasteFromHomogeneousSource(); 248 } 249 return commands; 250 } 251 252 } 253 260 254 261 255 public void actionPerformed(ActionEvent e) { 262 256 if (getCurrentDataSet().getSelected().isEmpty()) 263 257 return; 264 if (isHeteogeneousSource()) { 265 pasteFromHeterogeneousSource(getCurrentDataSet().getSelected()); 266 } else { 267 pasteFromHomogeneousSource(getCurrentDataSet().getSelected()); 268 } 269 } 270 271 @Override public void pasteBufferChanged(DataSet newPasteBuffer) { 258 TagPaster tagPaster = new TagPaster(Main.pasteBuffer.getDirectlyAdded(), getCurrentDataSet().getSelected()); 259 for (Command c:tagPaster.execute()) { 260 Main.main.undoRedo.add(c); 261 } 262 } 263 264 @Override public void pasteBufferChanged(PrimitiveDeepCopy newPasteBuffer) { 272 265 updateEnabledState(); 273 266 } … … 281 274 setEnabled( 282 275 !getCurrentDataSet().getSelected().isEmpty() 283 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.get Selected()).isEmpty()276 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.getDirectlyAdded()).isEmpty() 284 277 ); 285 278 } … … 289 282 setEnabled( 290 283 selection!= null && !selection.isEmpty() 291 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.get Selected()).isEmpty()284 && !TagCollection.unionOfAllPrimitives(Main.pasteBuffer.getDirectlyAdded()).isEmpty() 292 285 ); 293 286 } -
trunk/src/org/openstreetmap/josm/data/osm/Changeset.java
r2115 r2305 50 50 /** 51 51 * Creates a changeset with id <code>id</code>. If id > 0, sets incomplete to true. 52 * 52 * 53 53 * @param id the id 54 54 */ … … 61 61 /** 62 62 * Creates a clone of <code>other</code> 63 * 63 * 64 64 * @param other the other changeset. If null, creates a new changeset with id 0. 65 65 */ … … 192 192 this.tags.remove(key); 193 193 } 194 195 public void removeAll() { 196 this.tags.clear(); 197 } 198 194 199 195 200 public boolean hasEqualSemanticAttributes(Changeset other) { -
trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
r2282 r2305 1 1 // License: GPL. Copyright 2007 by Immanuel Scholz and others 2 2 package org.openstreetmap.josm.data.osm; 3 import static org.openstreetmap.josm.tools.I18n.tr;4 5 3 import java.awt.geom.Area; 6 4 import java.util.ArrayList; … … 16 14 17 15 import org.openstreetmap.josm.data.SelectionChangedListener; 18 import org.openstreetmap.josm.data.osm.QuadBuckets;19 16 20 17 /** … … 113 110 */ 114 111 public void addPrimitive(OsmPrimitive primitive) { 115 if (primitive == null)116 return;117 112 if (primitive instanceof Node) { 118 113 nodes.add((Node) primitive); … … 121 116 } else if (primitive instanceof Relation) { 122 117 relations.add((Relation) primitive); 118 } 119 } 120 121 public OsmPrimitive addPrimitive(PrimitiveData data) { 122 if (data instanceof NodeData) { 123 Node node = new Node((NodeData)data, this); 124 nodes.add(node); 125 return node; 126 } else if (data instanceof WayData) { 127 Way way = new Way((WayData)data, this); 128 ways.add(way); 129 return way; 130 } else if (data instanceof RelationData) { 131 Relation relation = new Relation((RelationData)data, this); 132 relations.add(relation); 133 return relation; 134 } else { 135 throw new AssertionError(); 123 136 } 124 137 } … … 145 158 } 146 159 160 public void removePrimitive(long id, OsmPrimitiveType type) { 161 removePrimitive(getPrimitiveById(id, type)); 162 } 163 147 164 public Collection<OsmPrimitive> getSelectedNodesAndWays() { 148 165 Collection<OsmPrimitive> sel = getSelected(nodes); … … 246 263 * Sets the current selection to the primitives in <code>selection</code>. 247 264 * Notifies all {@see SelectionChangedListener} if <code>fireSelectionChangeEvent</code> is true. 248 * 265 * 249 266 * @param selection the selection 250 267 * @param fireSelectionChangeEvent true, if the selection change listeners are to be notified; false, otherwise … … 265 282 * Sets the current selection to the primitives in <code>selection</code> 266 283 * and notifies all {@see SelectionChangedListener}. 267 * 284 * 268 285 * @param selection the selection 269 286 */ … … 275 292 * Adds the primitives in <code>selection</code> to the current selection 276 293 * and notifies all {@see SelectionChangedListener}. 277 * 294 * 278 295 * @param selection the selection 279 296 */ … … 285 302 * Adds the primitives in <code>selection</code> to the current selection. 286 303 * Notifies all {@see SelectionChangedListener} if <code>fireSelectionChangeEvent</code> is true. 287 * 304 * 288 305 * @param selection the selection 289 306 * @param fireSelectionChangeEvent true, if the selection change listeners are to be notified; false, otherwise … … 443 460 * exists 444 461 * 445 * @param id the id, > 0 required462 * @param id uniqueId of the primitive. Might be < 0 for newly created primitives 446 463 * @param type the type of the primitive. Must not be null. 447 464 * @return the primitive 448 * @exception IllegalArgumentException thrown, if id <= 0 449 * @exception IllegalArgumentException thrown, if type is null 450 * @exception IllegalArgumentException thrown, if type is neither NODE, or WAY or RELATION 465 * @exception NullPointerException thrown, if type is null 451 466 */ 452 467 public OsmPrimitive getPrimitiveById(long id, OsmPrimitiveType type) { 453 if (id <= 0)454 throw new IllegalArgumentException(tr("Parameter ''{0}'' > 0 expected. Got ''{1}''.", "id", id));455 if (id <= 0) 456 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null.", "type"));468 return getPrimitiveById(id, type, false); 469 } 470 471 public OsmPrimitive getPrimitiveById(long id, OsmPrimitiveType type, boolean createNew) { 457 472 Collection<? extends OsmPrimitive> primitives = null; 458 473 switch(type) { … … 462 477 } 463 478 for (OsmPrimitive primitive : primitives) { 464 if (primitive.getId() == id) return primitive; 465 } 466 return null; 479 if (primitive.getUniqueId() == id) return primitive; 480 } 481 482 if (createNew) { 483 OsmPrimitive result = null; 484 switch (type) { 485 case NODE: result = new Node(id, true); break; 486 case WAY: result = new Way(id, true); break; 487 case RELATION: result = new Relation(id, true); break; 488 } 489 addPrimitive(result); 490 return result; 491 } else { 492 return null; 493 } 467 494 } 468 495 … … 565 592 * Replies true if there is at least one primitive in this dataset with 566 593 * {@see OsmPrimitive#isModified()} == <code>true</code>. 567 * 594 * 568 595 * @return true if there is at least one primitive in this dataset with 569 596 * {@see OsmPrimitive#isModified()} == <code>true</code>. -
trunk/src/org/openstreetmap/josm/data/osm/NodeData.java
r2299 r2305 2 2 package org.openstreetmap.josm.data.osm; 3 3 4 import org.openstreetmap.josm.data.coor.CachedLatLon; 5 import org.openstreetmap.josm.data.coor.EastNorth; 4 6 import org.openstreetmap.josm.data.coor.LatLon; 5 7 6 8 public class NodeData extends PrimitiveData { 7 9 8 private LatLon coor; 10 private final CachedLatLon coor = new CachedLatLon(0, 0); 11 12 public NodeData() { 13 14 } 15 16 public NodeData(double lat, double lon, String... keys) { 17 setCoor(new LatLon(lat, lon)); 18 setKeysAsList(keys); 19 } 20 21 public NodeData(String... keys) { 22 setKeysAsList(keys); 23 } 24 25 public NodeData(NodeData data) { 26 super(data); 27 setCoor(data.getCoor()); 28 } 9 29 10 30 public LatLon getCoor() { … … 13 33 14 34 public void setCoor(LatLon coor) { 15 this.coor = coor; 35 this.coor.setCoor(coor); 36 } 37 38 public EastNorth getEastNorth() { 39 return this.coor.getEastNorth(); 40 } 41 42 public void setEastNorth(EastNorth eastNorth) { 43 this.coor.setEastNorth(eastNorth); 44 } 45 46 @Override 47 public NodeData makeCopy() { 48 return new NodeData(this); 49 } 50 51 @Override 52 public Node makePrimitive(DataSet dataSet) { 53 return new Node(this, dataSet); 16 54 } 17 55 -
trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
r2300 r2305 36 36 abstract public class OsmPrimitive implements Comparable<OsmPrimitive>, Tagged { 37 37 38 static final AtomicLong idCounter = new AtomicLong(0); 38 private static final AtomicLong idCounter = new AtomicLong(0); 39 40 static long generateUniqueId() { 41 return idCounter.decrementAndGet(); 42 } 39 43 40 44 private static final int FLAG_MODIFIED = 1 << 0; … … 164 168 throw new IllegalArgumentException(tr("Expected ID >= 0. Got {0}.", id)); 165 169 else if (id == 0) { 166 this.id = idCounter.decrementAndGet();170 this.id = generateUniqueId(); 167 171 } else { 168 172 this.id = id; … … 400 404 */ 401 405 public void clearOsmId() { 402 this.id = idCounter.decrementAndGet();406 this.id = generateUniqueId(); 403 407 this.version = 0; 404 408 this.incomplete = false; … … 456 460 if(directionKeys == null) { 457 461 directionKeys = Main.pref.getCollection("tags.direction", 458 Arrays.asList( new String[]{"oneway","incline","incline_steep","aerialway"}));462 Arrays.asList("oneway","incline","incline_steep","aerialway")); 459 463 } 460 464 return directionKeys; … … 841 845 842 846 protected void saveCommonAttributes(PrimitiveData data) { 843 data.setId( data.getId());847 data.setId(id); 844 848 data.getKeys().clear(); 845 849 data.getKeys().putAll(getKeys()); -
trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitiveType.java
r2181 r2305 5 5 public enum OsmPrimitiveType { 6 6 7 NODE ("node" ),8 WAY ("way" ),9 RELATION ("relation" );7 NODE ("node", Node.class, NodeData.class), 8 WAY ("way", Way.class, WayData.class), 9 RELATION ("relation", Relation.class, RelationData.class); 10 10 11 private String apiTypeName; 11 private final String apiTypeName; 12 private final Class<? extends OsmPrimitive> osmClass; 13 private final Class<? extends PrimitiveData> dataClass; 12 14 13 OsmPrimitiveType(String apiTypeName ) {15 OsmPrimitiveType(String apiTypeName, Class<? extends OsmPrimitive> osmClass, Class<? extends PrimitiveData> dataClass) { 14 16 this.apiTypeName = apiTypeName; 17 this.osmClass = osmClass; 18 this.dataClass = dataClass; 15 19 } 16 20 17 21 public String getAPIName() { 18 22 return apiTypeName; 23 } 24 25 public Class<? extends OsmPrimitive> getOsmClass() { 26 return osmClass; 27 } 28 29 public Class<? extends PrimitiveData> getDataClass() { 30 return dataClass; 19 31 } 20 32 … … 30 42 } 31 43 32 public static OsmPrimitiveType from(Class cls) {44 public static OsmPrimitiveType from(Class<? extends OsmPrimitive> cls) { 33 45 if (cls.equals(Node.class)) return NODE; 34 46 if (cls.equals(Way.class)) return WAY; 35 47 if (cls.equals(Relation.class)) return RELATION; 36 48 throw new IllegalArgumentException(tr("Parameter ''{0}'' is not an acceptable class. Got ''{1}''.", "cls", cls.toString())); 49 } 50 51 public static OsmPrimitiveType fromData(Class<? extends PrimitiveData> cls) { 52 if (cls.equals(NodeData.class)) return NODE; 53 if (cls.equals(WayData.class)) return WAY; 54 if (cls.equals(RelationData.class)) return RELATION; 55 throw new IllegalArgumentException(tr("Parameter ''{0}'' is not an acceptable class. Got ''{1}''.", "cls", cls.toString())); 56 } 57 58 public static OsmPrimitiveType fromData(PrimitiveData data) { 59 return fromData(data.getClass()); 37 60 } 38 61 -
trunk/src/org/openstreetmap/josm/data/osm/PrimitiveData.java
r2299 r2305 2 2 package org.openstreetmap.josm.data.osm; 3 3 4 import java.util.ArrayList; 5 import java.util.Collection; 4 6 import java.util.HashMap; 7 import java.util.List; 5 8 import java.util.Map; 6 9 … … 12 15 * 13 16 */ 14 public abstract class PrimitiveData {17 public abstract class PrimitiveData implements Tagged { 15 18 16 19 // Useful? … … 19 22 //private boolean selected; 20 23 //private boolean highlighted; 24 25 public PrimitiveData() { 26 id = OsmPrimitive.generateUniqueId(); 27 } 28 29 public PrimitiveData(PrimitiveData data) { 30 this.keys.putAll(data.keys); 31 this.modified = data.modified; 32 this.visible = data.visible; 33 this.deleted = data.deleted; 34 this.id = data.id; 35 this.user = data.user; 36 this.version = data.version; 37 this.timestamp = data.timestamp; 38 } 21 39 22 40 private final Map<String, String> keys = new HashMap<String, String>(); … … 75 93 } 76 94 95 public void clearOsmId() { 96 id = OsmPrimitive.generateUniqueId(); 97 } 98 99 public abstract PrimitiveData makeCopy(); 100 101 public abstract OsmPrimitive makePrimitive(DataSet dataSet); 77 102 78 103 @Override … … 94 119 } 95 120 121 // Tagged implementation 122 123 public String get(String key) { 124 return keys.get(key); 125 } 126 127 public boolean hasKeys() { 128 return !keys.isEmpty(); 129 } 130 131 public Collection<String> keySet() { 132 return keys.keySet(); 133 } 134 135 public void put(String key, String value) { 136 keys.put(key, value); 137 } 138 139 public void remove(String key) { 140 keys.remove(key); 141 } 142 143 public void removeAll() { 144 keys.clear(); 145 } 146 147 public void setKeys(Map<String, String> keys) { 148 this.keys.clear(); 149 this.keys.putAll(keys); 150 } 151 152 153 @SuppressWarnings("unchecked") 154 static public <T extends PrimitiveData> List<T> getFilteredList(Collection<T> list, OsmPrimitiveType type) { 155 List<T> ret = new ArrayList<T>(); 156 for(PrimitiveData p: list) { 157 if (type.getDataClass().isInstance(p)) { 158 ret.add((T)p); 159 } 160 } 161 return ret; 162 } 163 164 protected void setKeysAsList(String... keys) { 165 assert keys.length % 2 == 0; 166 for (int i=0; i<keys.length/2; i++) { 167 this.keys.put(keys[i * 2], keys[i * 2 + 1]); 168 } 169 } 170 171 96 172 97 173 } -
trunk/src/org/openstreetmap/josm/data/osm/Relation.java
r2284 r2305 205 205 foundMember = nodes.get(member.getMemberId()); 206 206 if (foundMember == nodeMarker) { 207 foundMember = new Node(member.getMemberId(), true);207 throw new AssertionError("Data consistency problem - relation with missing member detected"); 208 208 } 209 209 break; … … 211 211 foundMember = ways.get(member.getMemberId()); 212 212 if (foundMember == wayMarker) { 213 foundMember = new Way(member.getMemberId(), true);213 throw new AssertionError("Data consistency problem - relation with missing member detected"); 214 214 } 215 215 break; … … 217 217 foundMember = relations.get(member.getMemberId()); 218 218 if (foundMember == relationMarker) { 219 foundMember = new Relation(member.getMemberId(), true);219 throw new AssertionError("Data consistency problem - relation with missing member detected"); 220 220 } 221 221 break; -
trunk/src/org/openstreetmap/josm/data/osm/RelationData.java
r2299 r2305 9 9 private final List<RelationMemberData> members = new ArrayList<RelationMemberData>(); 10 10 11 public RelationData() { 12 13 } 14 15 public RelationData(RelationData data) { 16 super(data); 17 members.addAll(data.members); 18 } 19 11 20 public List<RelationMemberData> getMembers() { 12 21 return members; 22 } 23 24 @Override 25 public RelationData makeCopy() { 26 return new RelationData(this); 27 } 28 29 @Override 30 public Relation makePrimitive(DataSet dataSet) { 31 return new Relation(this, dataSet); 13 32 } 14 33 -
trunk/src/org/openstreetmap/josm/data/osm/RelationMemberData.java
r2299 r2305 4 4 public class RelationMemberData { 5 5 6 private String role;7 private long memberId;8 private OsmPrimitiveType memberType;6 private final String role; 7 private final long memberId; 8 private final OsmPrimitiveType memberType; 9 9 10 public RelationMemberData() { 11 10 public RelationMemberData(String role, OsmPrimitiveType type, long id) { 11 this.role = role; 12 this.memberType = type; 13 this.memberId = id; 12 14 } 13 15 14 16 public RelationMemberData(String role, OsmPrimitive primitive) { 15 this.role = role; 16 this.memberId = primitive.getUniqueId(); 17 this.memberType = OsmPrimitiveType.from(primitive); 17 this(role, OsmPrimitiveType.from(primitive), primitive.getUniqueId()); 18 18 } 19 19 … … 21 21 return memberId; 22 22 } 23 public void setMemberId(long memberId) {24 this.memberId = memberId;25 }26 23 public String getRole() { 27 24 return role; 28 25 } 29 public void setRole(String role) {30 this.role = role;31 }32 26 public OsmPrimitiveType getMemberType() { 33 27 return memberType; 34 }35 public void setMemberType(OsmPrimitiveType memberType) {36 this.memberType = memberType;37 28 } 38 29 -
trunk/src/org/openstreetmap/josm/data/osm/Tag.java
r2070 r2305 2 2 package org.openstreetmap.josm.data.osm; 3 3 4 import java.util.ArrayList;5 import java.util.Collections;6 import java.util.Iterator;7 import java.util.List;8 4 9 5 /** … … 21 17 */ 22 18 public Tag(){ 23 this.key = ""; 24 this.value = ""; 19 this("", ""); 25 20 } 26 21 … … 28 23 * Create a tag whose key is <code>key</code> and whose value is 29 24 * empty. 30 * 25 * 31 26 * @param key the key. If null, it is set to the empty key. 32 27 */ 33 28 public Tag(String key) { 34 this(); 35 this.key = key == null ? "" : key; 29 this(key, ""); 36 30 } 37 31 … … 39 33 * Creates a tag for a key and a value. If key and/or value are null, 40 34 * the empty value "" is assumed. 41 * 35 * 42 36 * @param key the key 43 37 * @param value the value … … 50 44 /** 51 45 * Creates clone of the tag <code>tag</code>. 52 * 53 * @param tag the tag. If null, creates an empty tag.46 * 47 * @param tag the tag. 54 48 */ 55 49 public Tag(Tag tag) { 56 if (tag != null) { 57 key = tag.getKey(); 58 value = tag.getValue(); 59 } 50 this(tag.getKey(), tag.getValue()); 60 51 } 61 52 62 53 /** 63 54 * Replies the key of the tag. This is never null. 64 * 55 * 65 56 * @return the key of the tag 66 57 */ … … 71 62 /** 72 63 * Replies the value of the tag. This is never null. 73 * 64 * 74 65 * @return the value of the tag 75 66 */ … … 86 77 * Replies true if the key of this tag is equal to <code>key</code>. 87 78 * If <code>key</code> is null, assumes the empty key. 88 * 79 * 89 80 * @param key the key 90 81 * @return true if the key of this tag is equal to <code>key</code> 91 82 */ 92 83 public boolean matchesKey(String key) { 93 if (key == null) {94 key = "";95 }96 84 return this.key.equals(key); 97 85 } … … 102 90 * <li>removing leading and trailing white space</li> 103 91 * <ul> 104 * 92 * 105 93 */ 106 94 public void normalize() { … … 113 101 final int prime = 31; 114 102 int result = 1; 115 result = prime * result + ((key == null) ? 0 : key.hashCode());116 result = prime * result + ((value == null) ? 0 : value.hashCode());103 result = prime * result + key.hashCode(); 104 result = prime * result + value.hashCode(); 117 105 return result; 118 106 } … … 120 108 @Override 121 109 public boolean equals(Object obj) { 122 if (this == obj) 123 return true; 124 if (obj == null) 110 if (obj instanceof Tag) { 111 Tag other = (Tag) obj; 112 return key.equals(other.getKey()) && value.equals(other.getValue()); 113 } else { 125 114 return false; 126 if (getClass() != obj.getClass()) 127 return false; 128 Tag other = (Tag) obj; 129 if (key == null) { 130 if (other.key != null) 131 return false; 132 } else if (!key.equals(other.key)) 133 return false; 134 if (value == null) { 135 if (other.value != null) 136 return false; 137 } else if (!value.equals(other.value)) 138 return false; 139 return true; 115 } 116 } 117 118 @Override 119 public String toString() { 120 return key + "=" + value; 140 121 } 141 122 } -
trunk/src/org/openstreetmap/josm/data/osm/TagCollection.java
r2181 r2305 17 17 * TagCollection is a collection of tags which can be used to manipulate 18 18 * tags managed by {@see OsmPrimitive}s. 19 * 19 * 20 20 * A TagCollection can be created: 21 21 * <ul> … … 25 25 * <li>from the intersection of all tags managed by a collection of primitives with {@see #commonToAllPrimitives(Collection)}</li> 26 26 * </ul> 27 * 27 * 28 28 * It provides methods to query the collection, like {@see #size()}, {@see #hasTagsFor(String)}, etc. 29 * 29 * 30 30 * Basic set operations allow to create the union, the intersection and the difference 31 31 * of tag collections, see {@see #union(TagCollection)}, {@see #intersect(TagCollection)}, 32 32 * and {@see #minus(TagCollection)}. 33 * 33 * 34 34 * 35 35 */ … … 40 40 * {@see OsmPrimitive}. If <code>primitive</code> is null, replies 41 41 * an empty tag collection. 42 * 42 * 43 43 * @param primitive the primitive 44 44 * @return a tag collection with the tags managed by a specific 45 45 * {@see OsmPrimitive} 46 46 */ 47 public static TagCollection from( OsmPrimitiveprimitive) {47 public static TagCollection from(Tagged primitive) { 48 48 TagCollection tags = new TagCollection(); 49 49 for (String key: primitive.keySet()) { … … 62 62 * a collection of primitives 63 63 */ 64 public static TagCollection unionOfAllPrimitives(Collection<? extends OsmPrimitive> primitives) {64 public static TagCollection unionOfAllPrimitives(Collection<? extends Tagged> primitives) { 65 65 TagCollection tags = new TagCollection(); 66 66 if (primitives == null) return tags; 67 for ( OsmPrimitiveprimitive: primitives) {67 for (Tagged primitive: primitives) { 68 68 if (primitive == null) { 69 69 continue; … … 78 78 * <code>primitives</code>. Replies an empty tag collection of <code>primitives</code> 79 79 * is null. 80 * 80 * 81 81 * @param primitives the primitives 82 82 * @return a tag collection with the tags which are common to all primitives 83 83 */ 84 public static TagCollection commonToAllPrimitives(Collection<? extends OsmPrimitive> primitives) {84 public static TagCollection commonToAllPrimitives(Collection<? extends Tagged> primitives) { 85 85 TagCollection tags = new TagCollection(); 86 86 if (primitives == null || primitives.isEmpty()) return tags; … … 91 91 // intersect with the others 92 92 // 93 for ( OsmPrimitiveprimitive: primitives) {93 for (Tagged primitive: primitives) { 94 94 if (primitive == null) { 95 95 continue; … … 103 103 * Replies a tag collection with the union of the tags which are common to all primitives in 104 104 * the dataset <code>ds</code>. Returns an empty tag collection of <code>ds</code> is null. 105 * 105 * 106 106 * @param ds the dataset 107 107 * @return a tag collection with the union of the tags which are common to all primitives in … … 129 129 * Creates a clone of the tag collection <code>other</code>. Creats an empty 130 130 * tag collection if <code>other</code> is null. 131 * 131 * 132 132 * @param other the other collection 133 133 */ … … 141 141 /** 142 142 * Replies the number of tags in this tag collection 143 * 143 * 144 144 * @return the number of tags in this tag collection 145 145 */ … … 150 150 /** 151 151 * Replies true if this tag collection is empty 152 * 152 * 153 153 * @return true if this tag collection is empty; false, otherwise 154 154 */ … … 159 159 /** 160 160 * Adds a tag to the tag collection. If <code>tag</code> is null, nothing is added. 161 * 161 * 162 162 * @param tag the tag to add 163 163 */ … … 171 171 * Adds a collection of tags to the tag collection. If <code>tags</code> is null, nothing 172 172 * is added. null values in the collection are ignored. 173 * 173 * 174 174 * @param tags the collection of tags 175 175 */ … … 184 184 * Adds the tags of another tag collection to this collection. Adds nothing, if 185 185 * <code>tags</code> is null. 186 * 186 * 187 187 * @param tags the other tag collection 188 188 */ … … 195 195 * Removes a specific tag from the tag collection. Does nothing if <code>tag</code> is 196 196 * null. 197 * 197 * 198 198 * @param tag the tag to be removed 199 199 */ … … 206 206 * Removes a collection of tags from the tag collection. Does nothing if <code>tags</code> is 207 207 * null. 208 * 208 * 209 209 * @param tags the tags to be removed 210 210 */ … … 217 217 * Removes all tags in the tag collection <code>tags</code> from the current tag collection. 218 218 * Does nothing if <code>tags</code> is null. 219 * 219 * 220 220 * @param tags the tag collection to be removed. 221 221 */ … … 228 228 * Removes all tags whose keys are equal to <code>key</code>. Does nothing if <code>key</code> 229 229 * is null. 230 * 230 * 231 231 * @param key the key to be removed 232 232 */ … … 244 244 * Removes all tags whose key is in the collection <code>keys</code>. Does nothing if 245 245 * <code>keys</code> is null. 246 * 246 * 247 247 * @param keys the collection of keys to be removed 248 248 */ … … 256 256 /** 257 257 * Replies true if the this tag collection contains <code>tag</code>. 258 * 258 * 259 259 * @param tag the tag to look up 260 260 * @return true if the this tag collection contains <code>tag</code>; false, otherwise … … 266 266 /** 267 267 * Replies true if this tag collection contains at least one tag with key <code>key</code>. 268 * 268 * 269 269 * @param key the key to look up 270 270 * @return true if this tag collection contains at least one tag with key <code>key</code>; false, otherwise … … 281 281 * Replies true if this tag collection contains all tags in <code>tags</code>. Replies 282 282 * false, if tags is null. 283 * 283 * 284 284 * @param tags the tags to look up 285 285 * @return true if this tag collection contains all tags in <code>tags</code>. Replies … … 288 288 public boolean containsAll(Collection<Tag> tags) { 289 289 if (tags == null) return false; 290 return t ags.containsAll(tags);290 return this.tags.containsAll(tags); 291 291 } 292 292 … … 294 294 * Replies true if this tag collection at least one tag for every key in <code>keys</code>. 295 295 * Replies false, if <code>keys</code> is null. null values in <code>keys</code> are ignored. 296 * 296 * 297 297 * @param keys the keys to lookup 298 298 * @return true if this tag collection at least one tag for every key in <code>keys</code>. … … 311 311 /** 312 312 * Replies the number of tags with key <code>key</code> 313 * 313 * 314 314 * @param key the key to look up 315 315 * @return the number of tags with key <code>key</code>. 0, if key is null. … … 328 328 /** 329 329 * Replies true if there is at least one tag for the given key. 330 * 330 * 331 331 * @param key the key to look up 332 332 * @return true if there is at least one tag for the given key. false, if key is null. … … 339 339 * Replies true it there is at least one tag with a non empty value for key. 340 340 * Replies false if key is null. 341 * 341 * 342 342 * @param key the key 343 343 * @return true it there is at least one tag with a non empty value for key. … … 354 354 * if the value of this tag is not empty. Replies false if key is 355 355 * null. 356 * 356 * 357 357 * @param key the key 358 358 * @return true if there is exactly one tag for <code>key</code> and … … 368 368 * Replies true if there is a tag with an empty value for <code>key</code>. 369 369 * Replies false, if key is null. 370 * 370 * 371 371 * @param key the key 372 372 * @return true if there is a tag with an empty value for <code>key</code> … … 381 381 * Replies true if there is exactly one tag for <code>key</code> and if 382 382 * the value for this tag is empty. Replies false if key is null. 383 * 383 * 384 384 * @param key the key 385 385 * @return true if there is exactly one tag for <code>key</code> and if … … 395 395 * Replies a tag collection with the tags for a given key. Replies an empty collection 396 396 * if key is null. 397 * 397 * 398 398 * @param key the key to look up 399 399 * @return a tag collection with the tags for a given key. Replies an empty collection … … 415 415 * Replies a tag collection with all tags whose key is equal to one of the keys in 416 416 * <code>keys</code>. Replies an empty collection if keys is null. 417 * 417 * 418 418 * @param keys the keys to look up 419 419 * @return a tag collection with all tags whose key is equal to one of the keys in … … 434 434 /** 435 435 * Replies the tags of this tag collection as set 436 * 436 * 437 437 * @return the tags of this tag collection as set 438 438 */ … … 444 444 * Replies the tags of this tag collection as list. 445 445 * Note that the order of the list is not preserved between method invocations. 446 * 446 * 447 447 * @return the tags of this tag collection as list. 448 448 */ … … 453 453 /** 454 454 * Replies an iterator to iterate over the tags in this collection 455 * 455 * 456 456 * @return the iterator 457 457 */ … … 462 462 /** 463 463 * Replies the set of keys of this tag collection. 464 * 464 * 465 465 * @return the set of keys of this tag collection 466 466 */ … … 475 475 /** 476 476 * Replies the set of keys which have at least 2 matching tags. 477 * 477 * 478 478 * @return the set of keys which have at least 2 matching tags. 479 479 */ … … 496 496 * Sets a unique tag for the key of this tag. All other tags with the same key are 497 497 * removed from the collection. Does nothing if tag is null. 498 * 498 * 499 499 * @param tag the tag to set 500 500 */ … … 509 509 * removed from the collection. Assume the empty string for key and value if either 510 510 * key or value is null. 511 * 511 * 512 512 * @param key the key 513 513 * @param value the value … … 520 520 /** 521 521 * Replies the set of values in this tag collection 522 * 522 * 523 523 * @return the set of values 524 524 */ … … 534 534 * Replies the set of values for a given key. Replies an empty collection if there 535 535 * are no values for the given key. 536 * 536 * 537 537 * @param key the key to look up 538 538 * @return the set of values for a given key. Replies an empty collection if there … … 552 552 /** 553 553 * Replies true if for every key there is one tag only, i.e. exactly one value. 554 * 554 * 555 555 * @return 556 556 */ … … 562 562 * Applies this tag collection to an {@see OsmPrimitive}. Does nothing if 563 563 * primitive is null 564 * 564 * 565 565 * @param primitive the primitive 566 566 * @throws IllegalStateException thrown if this tag collection can't be applied 567 567 * because there are keys with multiple values 568 568 */ 569 public void applyTo( OsmPrimitiveprimitive) throws IllegalStateException {569 public void applyTo(Tagged primitive) throws IllegalStateException { 570 570 if (primitive == null) return; 571 571 if (! isApplicableToPrimitive()) … … 583 583 * Applies this tag collection to a collection of {@see OsmPrimitive}s. Does nothing if 584 584 * primitives is null 585 * 585 * 586 586 * @param primitives the collection of primitives 587 587 * @throws IllegalStateException thrown if this tag collection can't be applied 588 588 * because there are keys with multiple values 589 589 */ 590 public void applyTo(Collection<? extends OsmPrimitive> primitives) throws IllegalStateException{590 public void applyTo(Collection<? extends Tagged> primitives) throws IllegalStateException{ 591 591 if (primitives == null) return; 592 592 if (! isApplicableToPrimitive()) 593 593 throw new IllegalStateException(tr("Tag collection can't be applied to a primitive because there are keys with multiple values.")); 594 for ( OsmPrimitiveprimitive: primitives) {594 for (Tagged primitive: primitives) { 595 595 applyTo(primitive); 596 596 } … … 600 600 * Replaces the tags of an {@see OsmPrimitive} by the tags in this collection . Does nothing if 601 601 * primitive is null 602 * 602 * 603 603 * @param primitive the primitive 604 604 * @throws IllegalStateException thrown if this tag collection can't be applied 605 605 * because there are keys with multiple values 606 606 */ 607 public void replaceTagsOf( OsmPrimitiveprimitive) throws IllegalStateException {607 public void replaceTagsOf(Tagged primitive) throws IllegalStateException { 608 608 if (primitive == null) return; 609 609 if (! isApplicableToPrimitive()) … … 618 618 * Replaces the tags of a collection of{@see OsmPrimitive}s by the tags in this collection. 619 619 * Does nothing if primitives is null 620 * 620 * 621 621 * @param primitive the collection of primitives 622 622 * @throws IllegalStateException thrown if this tag collection can't be applied 623 623 * because there are keys with multiple values 624 624 */ 625 public void replaceTagsOf(Collection<? extends OsmPrimitive> primitives) throws IllegalStateException {625 public void replaceTagsOf(Collection<? extends Tagged> primitives) throws IllegalStateException { 626 626 if (primitives == null) return; 627 627 if (! isApplicableToPrimitive()) 628 628 throw new IllegalStateException(tr("Tag collection can't be applied to a primitive because there are keys with multiple values.")); 629 for ( OsmPrimitiveprimitive: primitives) {629 for (Tagged primitive: primitives) { 630 630 replaceTagsOf(primitive); 631 631 } … … 634 634 /** 635 635 * Builds the intersection of this tag collection and another tag collection 636 * 636 * 637 637 * @param other the other tag collection. If null, replies an empty tag collection. 638 638 * @return the intersection of this tag collection and another tag collection … … 653 653 /** 654 654 * Replies the difference of this tag collection and another tag collection 655 * 655 * 656 656 * @param other the other tag collection. May be null. 657 657 * @return the difference of this tag collection and another tag collection … … 667 667 /** 668 668 * Replies the union of this tag collection and another tag collection 669 * 669 * 670 670 * @param other the other tag collection. May be null. 671 671 * @return the union of this tag collection and another tag collection … … 690 690 /** 691 691 * Replies the concatenation of all tag values (concatenated by a semicolon) 692 * 692 * 693 693 * @return the concatenation of all tag values 694 694 */ … … 707 707 return buffer.toString(); 708 708 } 709 710 @Override 711 public String toString() { 712 return tags.toString(); 713 } 709 714 } -
trunk/src/org/openstreetmap/josm/data/osm/Tagged.java
r2115 r2305 6 6 /** 7 7 * Objects implement Tagged if they provide a map of key/value pairs. 8 * 9 * 8 * 9 * 10 10 */ 11 11 // FIXME: better naming? setTags(), getTags(), getKeys() instead of keySet() ? … … 14 14 /** 15 15 * Sets the map of key/value pairs 16 * 16 * 17 17 * @param keys the map of key value pairs. If null, reset to the empty map. 18 18 */ … … 21 21 /** 22 22 * Replies the map of key/value pairs. Never null, but may be the empty map. 23 * 23 * 24 24 * @return the map of key/value pairs 25 25 */ … … 28 28 /** 29 29 * Sets a key/value pairs 30 * 30 * 31 31 * @param key the key 32 32 * @param value the value. If null, removes the key/value pair. … … 36 36 /** 37 37 * Replies the value of the given key; null, if there is no value for this key 38 * 38 * 39 39 * @param key the key 40 40 * @return the value … … 44 44 /** 45 45 * Removes a given key/value pair 46 * 46 * 47 47 * @param key the key 48 48 */ … … 51 51 /** 52 52 * Replies true, if there is at least one key/value pair; false, otherwise 53 * 53 * 54 54 * @return true, if there is at least one key/value pair; false, otherwise 55 55 */ … … 58 58 /** 59 59 * Replies the set of keys 60 * 60 * 61 61 * @return the set of keys 62 62 */ 63 63 Collection<String> keySet(); 64 65 /** 66 * Removes all tags 67 */ 68 void removeAll(); 64 69 } -
trunk/src/org/openstreetmap/josm/data/osm/Way.java
r2284 r2305 196 196 newNodes.add(foundNodes.get(nodeId)); 197 197 } else { 198 newNodes.add(new Node(nodeId, true));198 throw new AssertionError("Data consistency problem - way with missing node detected"); 199 199 } 200 200 } -
trunk/src/org/openstreetmap/josm/data/osm/WayData.java
r2299 r2305 9 9 private final List<Long> nodes = new ArrayList<Long>(); 10 10 11 public WayData() { 12 13 } 14 15 public WayData(WayData data) { 16 super(data); 17 nodes.addAll(data.getNodes()); 18 } 19 11 20 public List<Long> getNodes() { 12 21 return nodes; 22 } 23 24 @Override 25 public WayData makeCopy() { 26 return new WayData(this); 27 } 28 29 @Override 30 public OsmPrimitive makePrimitive(DataSet dataSet) { 31 return new Way(this, dataSet); 13 32 } 14 33
Note:
See TracChangeset
for help on using the changeset viewer.