001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.command;
003
004 import static org.openstreetmap.josm.tools.I18n.trn;
005
006 import java.util.ArrayList;
007 import java.util.Collection;
008 import java.util.HashSet;
009 import java.util.List;
010 import javax.swing.Icon;
011
012 import javax.swing.JLabel;
013
014 import org.openstreetmap.josm.data.osm.DataSet;
015 import org.openstreetmap.josm.data.osm.Node;
016 import org.openstreetmap.josm.data.osm.NodeData;
017 import org.openstreetmap.josm.data.osm.OsmPrimitive;
018 import org.openstreetmap.josm.data.osm.PrimitiveData;
019 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
020
021 /**
022 * Add primitives to a data layer.
023 *
024 */
025 public class AddPrimitivesCommand extends Command {
026
027 private List<PrimitiveData> data = new ArrayList<PrimitiveData>();
028
029 // only filled on undo
030 private List<OsmPrimitive> createdPrimitives = null;
031
032 public AddPrimitivesCommand(List<PrimitiveData> data) {
033 this.data.addAll(data);
034 }
035
036 public AddPrimitivesCommand(List<PrimitiveData> data, OsmDataLayer layer) {
037 super(layer);
038 this.data.addAll(data);
039 }
040
041 @SuppressWarnings("null")
042 @Override public boolean executeCommand() {
043 List<OsmPrimitive> newPrimitives;
044 if (createdPrimitives == null) { // first time execution
045 newPrimitives = new ArrayList<OsmPrimitive>(data.size());
046
047 for (PrimitiveData pd : data) {
048 OsmPrimitive primitive = getLayer().data.getPrimitiveById(pd);
049 boolean created = primitive == null;
050 if (created) {
051 primitive = pd.getType().newInstance(pd.getUniqueId(), true);
052 }
053 if (pd instanceof NodeData) { // Load nodes immediately because they can't be added to dataset without coordinates
054 primitive.load(pd);
055 }
056 if (created) {
057 getLayer().data.addPrimitive(primitive);
058 }
059 newPrimitives.add(primitive);
060 }
061
062 //Then load ways and relations
063 for (int i=0; i<newPrimitives.size(); i++) {
064 if (!(newPrimitives.get(i) instanceof Node)) {
065 newPrimitives.get(i).load(data.get(i));
066 }
067 }
068 } else { // redo
069 // When redoing this command, we have to add the same objects, otherwise
070 // a subsequent command (e.g. MoveCommand) cannot be redone.
071 for (OsmPrimitive osm : createdPrimitives) {
072 getLayer().data.addPrimitive(osm);
073 }
074 newPrimitives = createdPrimitives;
075 }
076
077 getLayer().data.setSelected(newPrimitives);
078 return true;
079 }
080
081 @Override public void undoCommand() {
082 DataSet ds = getLayer().data;
083
084 if (createdPrimitives == null) {
085 createdPrimitives = new ArrayList<OsmPrimitive>(data.size());
086
087 for (PrimitiveData p : data) {
088 createdPrimitives.add(ds.getPrimitiveById(p));
089 }
090 createdPrimitives = PurgeCommand.topoSort(createdPrimitives);
091
092 for (PrimitiveData p : data) {
093 ds.removePrimitive(p);
094 }
095 data = null;
096
097 } else {
098 for (OsmPrimitive osm : createdPrimitives) {
099 ds.removePrimitive(osm);
100 }
101 }
102 }
103
104 @Override
105 public String getDescriptionText() {
106 int size = data != null ? data.size() : createdPrimitives.size();
107 return trn("Added {0} object", "Added {0} objects", size, size);
108 }
109
110 @Override
111 public Icon getDescriptionIcon() {
112 return null;
113 }
114
115 @Override
116 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
117 Collection<OsmPrimitive> added) {
118 // Does nothing because we don't want to create OsmPrimitives.
119 }
120
121 @Override
122 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
123 if (createdPrimitives != null)
124 return createdPrimitives;
125
126 Collection<OsmPrimitive> prims = new HashSet<OsmPrimitive>();
127 for (PrimitiveData d : data) {
128 OsmPrimitive osm = getLayer().data.getPrimitiveById(d);
129 if (osm == null)
130 throw new RuntimeException();
131 prims.add(osm);
132 }
133 return prims;
134 }
135 }