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 }