Ignore:
Timestamp:
2008-09-18T15:19:00+02:00 (16 years ago)
Author:
stoecker
Message:

make advanced object deletion available for outside, so validator can use it

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r755 r988  
    55import static org.openstreetmap.josm.tools.I18n.trn;
    66
     7import java.util.ArrayList;
    78import java.util.Collection;
    89import java.util.Collections;
     10import java.util.HashMap;
     11import java.util.HashSet;
     12import java.util.Iterator;
     13import java.util.LinkedList;
     14import java.util.List;
    915
    1016import javax.swing.JLabel;
     17import javax.swing.JOptionPane;
    1118import javax.swing.tree.DefaultMutableTreeNode;
    1219import javax.swing.tree.MutableTreeNode;
    1320
     21import org.openstreetmap.josm.Main;
     22import org.openstreetmap.josm.data.osm.Node;
    1423import org.openstreetmap.josm.data.osm.OsmPrimitive;
     24import org.openstreetmap.josm.data.osm.Relation;
     25import org.openstreetmap.josm.data.osm.RelationMember;
     26import org.openstreetmap.josm.data.osm.Way;
     27import org.openstreetmap.josm.data.osm.WaySegment;
     28import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    1529import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
    1630import org.openstreetmap.josm.tools.ImageProvider;
     
    8498                return root;
    8599        }
     100
     101        /**
     102         * Delete the primitives and everything they reference.
     103         *
     104         * If a node is deleted, the node and all ways and relations
     105         * the node is part of are deleted as well.
     106         *
     107         * If a way is deleted, all relations the way is member of are also deleted.
     108         *
     109         * If a way is deleted, only the way and no nodes are deleted.
     110         *
     111         * @param selection The list of all object to be deleted.
     112         * @return command A command to perform the deletions, or null of there is
     113         * nothing to delete.
     114         */
     115        public static Command deleteWithReferences(Collection<? extends OsmPrimitive> selection) {
     116                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds);
     117                for (OsmPrimitive osm : selection)
     118                        osm.visit(v);
     119                v.data.addAll(selection);
     120                if (v.data.isEmpty())
     121                        return null;
     122                return new DeleteCommand(v.data);
     123        }
     124
     125        /**
     126         * Try to delete all given primitives.
     127         *
     128         * If a node is used by a way, it's removed from that way.  If a node or a
     129         * way is used by a relation, inform the user and do not delete.
     130         *
     131         * If this would cause ways with less than 2 nodes to be created, delete
     132         * these ways instead.  If they are part of a relation, inform the user
     133         * and do not delete.
     134         *
     135         * @param selection The objects to delete.
     136         * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
     137         * @return command A command to perform the deletions, or null of there is
     138         * nothing to delete.
     139         */
     140        private static int testRelation(Relation ref, OsmPrimitive osm)
     141        {
     142                NameVisitor n = new NameVisitor();
     143                ref.visit(n);
     144                NameVisitor s = new NameVisitor();
     145                osm.visit(s);
     146                String role = new String();
     147                for (RelationMember m : ref.members)
     148                {
     149                        if (m.member == osm)
     150                        {
     151                                role = m.role;
     152                                break;
     153                        }
     154                }
     155                if (role.length() > 0)
     156                {
     157                        return JOptionPane.showConfirmDialog(Main.parent,
     158                        tr("Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?", s.name, n.name, role),
     159                        tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
     160                }
     161                else
     162                {
     163                        return JOptionPane.showConfirmDialog(Main.parent,
     164                        tr("Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?", s.name, n.name),
     165                        tr("Conflicting relation"), JOptionPane.YES_NO_OPTION);
     166                }
     167        }
     168
     169        public static Command delete(Collection<? extends OsmPrimitive> selection)
     170        {
     171                return delete(selection, true);
     172        }
     173
     174        public static Command delete(Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
     175                if (selection.isEmpty()) return null;
     176
     177                Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(selection);
     178                Collection<Way> waysToBeChanged = new HashSet<Way>();
     179                HashMap<OsmPrimitive, Collection<OsmPrimitive>> relationsToBeChanged = new HashMap<OsmPrimitive, Collection<OsmPrimitive>>();
     180
     181                if (alsoDeleteNodesInWay) {
     182                        // Delete untagged nodes that are to be unreferenced.
     183                        Collection<OsmPrimitive> delNodes = new HashSet<OsmPrimitive>();
     184                        for (OsmPrimitive osm : del) {
     185                                if (osm instanceof Way) {
     186                                        for (Node n : ((Way)osm).nodes) {
     187                                                if (!n.tagged) {
     188                                                        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     189                                                        n.visit(v);
     190                                                        v.data.removeAll(del);
     191                                                        if (v.data.isEmpty()) {
     192                                                                delNodes.add(n);
     193                                                        }
     194                                                }
     195                                        }
     196                                }
     197                        }
     198                        del.addAll(delNodes);
     199                }
     200               
     201                for (OsmPrimitive osm : del) {
     202                        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     203                        osm.visit(v);
     204                        for (OsmPrimitive ref : v.data) {
     205                                if (del.contains(ref)) continue;
     206                                if (ref instanceof Way) {
     207                                        waysToBeChanged.add((Way) ref);
     208                                } else if (ref instanceof Relation) {
     209                                        if (testRelation((Relation)ref, osm) == JOptionPane.YES_OPTION)
     210                                        {
     211                                                Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
     212                                                if(relset == null) relset = new HashSet<OsmPrimitive>();
     213                                                relset.add(osm);
     214                                                relationsToBeChanged.put(ref, relset);
     215                                        }
     216                                        else
     217                                                return null;
     218                                } else {
     219                                        return null;
     220                                }
     221                        }
     222                }
     223
     224                Collection<Command> cmds = new LinkedList<Command>();
     225                for (Way w : waysToBeChanged) {
     226                        Way wnew = new Way(w);
     227                        wnew.nodes.removeAll(del);
     228                        if (wnew.nodes.size() < 2) {
     229                                del.add(w);
     230
     231                                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.ds, false);
     232                                w.visit(v);
     233                                for (OsmPrimitive ref : v.data) {
     234                                        if (del.contains(ref)) continue;
     235                                        if (ref instanceof Relation) {
     236                                                Boolean found = false;
     237                                                Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
     238                                                if (relset == null)
     239                                                        relset = new HashSet<OsmPrimitive>();
     240                                                else
     241                                                {
     242                                                        for (OsmPrimitive m : relset) {
     243                                                                if(m == w)
     244                                                                {
     245                                                                        found = true;
     246                                                                        break;
     247                                                                }
     248                                                        }
     249                                                }
     250                                                if (!found)
     251                                                {
     252                                                        if (testRelation((Relation)ref, w) == JOptionPane.YES_OPTION)
     253                                                        {
     254                                                                relset.add(w);
     255                                                                relationsToBeChanged.put(ref, relset);
     256                                                        }
     257                                                        else
     258                                                                return null;
     259                                                }
     260                                        } else {
     261                                                return null;
     262                                        }
     263                                }
     264                        } else {
     265                                cmds.add(new ChangeCommand(w, wnew));
     266                        }
     267                }
     268
     269                Iterator<OsmPrimitive> iterator = relationsToBeChanged.keySet().iterator();
     270                while(iterator.hasNext())
     271                {
     272                        Relation cur = (Relation)iterator.next();
     273                        Relation rel = new Relation(cur);
     274                        for(OsmPrimitive osm : relationsToBeChanged.get(cur))
     275                        {
     276                                for (RelationMember rm : rel.members) {
     277                                        if (rm.member == osm)
     278                                        {
     279                                                RelationMember mem = new RelationMember();
     280                                                mem.role = rm.role;
     281                                                mem.member = rm.member;
     282                                                rel.members.remove(mem);
     283                                                break;
     284                                        }
     285                                }
     286                        }
     287                        cmds.add(new ChangeCommand(cur, rel));
     288                }
     289
     290                if (!del.isEmpty()) cmds.add(new DeleteCommand(del));
     291
     292                return new SequenceCommand(tr("Delete"), cmds);
     293        }
     294
     295        public static Command deleteWaySegment(WaySegment ws) {
     296                List<Node> n1 = new ArrayList<Node>(),
     297                        n2 = new ArrayList<Node>();
     298
     299                n1.addAll(ws.way.nodes.subList(0, ws.lowerIndex + 1));
     300                n2.addAll(ws.way.nodes.subList(ws.lowerIndex + 1, ws.way.nodes.size()));
     301
     302                if (n1.size() < 2 && n2.size() < 2) {
     303                        return new DeleteCommand(Collections.singleton(ws.way));
     304                }
     305               
     306                Way wnew = new Way(ws.way);
     307                wnew.nodes.clear();
     308
     309                if (n1.size() < 2) {
     310                        wnew.nodes.addAll(n2);
     311                        return new ChangeCommand(ws.way, wnew);
     312                } else if (n2.size() < 2) {
     313                        wnew.nodes.addAll(n1);
     314                        return new ChangeCommand(ws.way, wnew);
     315                } else {
     316                        Collection<Command> cmds = new LinkedList<Command>();
     317
     318                        wnew.nodes.addAll(n1);
     319                        cmds.add(new ChangeCommand(ws.way, wnew));
     320
     321                        Way wnew2 = new Way();
     322                        if (wnew.keys != null) {
     323                                wnew2.keys = new HashMap<String, String>(wnew.keys);
     324                                wnew2.checkTagged();
     325                                wnew2.checkDirectionTagged();
     326                        }
     327                        wnew2.nodes.addAll(n2);
     328                        cmds.add(new AddCommand(wnew2));
     329
     330                        return new SequenceCommand(tr("Split way segment"), cmds);
     331                }
     332        }
    86333}
Note: See TracChangeset for help on using the changeset viewer.