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    }