Ticket #7458: CreateMultipolygonAction.java.patch

File CreateMultipolygonAction.java.patch, 5.6 KB (added by akks, 14 years ago)
  • src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java

     
    66import java.awt.event.ActionEvent;
    77import java.awt.event.KeyEvent;
    88import java.util.ArrayList;
     9import java.util.Arrays;
    910import java.util.Collection;
    1011import java.util.HashMap;
    1112import java.util.List;
    1213import java.util.Map;
    1314
     15import java.util.Set;
     16import java.util.TreeSet;
    1417import javax.swing.JOptionPane;
    1518
    1619import javax.swing.SwingUtilities;
    1720import org.openstreetmap.josm.Main;
    1821import org.openstreetmap.josm.command.AddCommand;
     22import org.openstreetmap.josm.command.ChangeCommand;
    1923import org.openstreetmap.josm.command.ChangePropertyCommand;
    2024import org.openstreetmap.josm.command.Command;
    2125import org.openstreetmap.josm.command.SequenceCommand;
     
    98102
    99103        } else {
    100104            //Just add the relation
    101             List<Command> list = this.removeTagsFromInnerWays(relation);
     105            List<Command> list = this.removeTagsFromWaysIfNeeded(relation);
    102106            list.add(new AddCommand(relation));
    103107            Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list));
    104108            // Use 'SwingUtilities.invokeLater' to make sure the relationListDialog
     
    172176        return rel;
    173177    }
    174178
     179    static public final List<String> DEFAULT_LINEAR_TAGS = Arrays.asList(new String[] {"barrier", "source"});
     180    private static final Set<String> REMOVE_FROM_BOUNDARY_TAGS = new TreeSet<String>(Arrays.asList(new String[] {
     181                "boundary", "boundary_type", "type", "admin_level"
     182            }));
     183
    175184    /**
     185     * This method removes tags/value pairs from inner and outer ways and put them on relation if necessary
     186     * Function was extended in reltoolbox plugin by Zverikk and copied back to the core
     187     * @param relation
     188     */
     189    private List<Command> removeTagsFromWaysIfNeeded( Relation relation ) {
     190        Map<String, String> values = new HashMap<String, String>();
     191
     192        if( relation.hasKeys() ) {
     193            for( String key : relation.keySet() ) {
     194                values.put(key, relation.get(key));
     195            }
     196        }
     197
     198        List<Way> innerWays = new ArrayList<Way>();
     199        List<Way> outerWays = new ArrayList<Way>();
     200
     201        Set<String> conflictingKeys = new TreeSet<String>();
     202
     203        for( RelationMember m : relation.getMembers() ) {
     204
     205            if( m.hasRole() && "inner".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys() ) {
     206                innerWays.add(m.getWay());
     207            }
     208
     209            if( m.hasRole() && "outer".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys() ) {
     210                Way way = m.getWay();
     211                outerWays.add(way);
     212                for( String key : way.keySet() ) {
     213                    if( !values.containsKey(key) ) { //relation values take precedence
     214                        values.put(key, way.get(key));
     215                    } else if( !relation.hasKey(key) && !values.get(key).equals(way.get(key)) ) {
     216                        conflictingKeys.add(key);
     217                    }
     218                }
     219            }
     220        }
     221
     222        // filter out empty key conflicts - we need second iteration
     223        boolean isBoundary = Main.pref.getBoolean("multipoly.boundary", false);
     224        if( isBoundary || !Main.pref.getBoolean("multipoly.alltags", false) )
     225            for( RelationMember m : relation.getMembers() )
     226                if( m.hasRole() && m.getRole().equals("outer") && m.isWay() )
     227                    for( String key : values.keySet() )
     228                        if( !m.getWay().hasKey(key) && !relation.hasKey(key) )
     229                            conflictingKeys.add(key);
     230
     231        for( String key : conflictingKeys )
     232            values.remove(key);
     233
     234        for( String linearTag : Main.pref.getCollection("multipoly.lineartagstokeep", DEFAULT_LINEAR_TAGS) )
     235            values.remove(linearTag);
     236
     237        if( values.containsKey("natural") && values.get("natural").equals("coastline") )
     238            values.remove("natural");
     239
     240        String name = values.get("name");
     241        if( isBoundary ) {
     242            Set<String> keySet = new TreeSet<String>(values.keySet());
     243            for( String key : keySet )
     244                if( !REMOVE_FROM_BOUNDARY_TAGS.contains(key) )
     245                    values.remove(key);
     246        }
     247
     248        values.put("area", "yes");
     249
     250        List<Command> commands = new ArrayList<Command>();
     251        boolean moveTags = Main.pref.getBoolean("multipoly.movetags", true);
     252
     253        for( String key : values.keySet() ) {
     254            List<OsmPrimitive> affectedWays = new ArrayList<OsmPrimitive>();
     255            String value = values.get(key);
     256
     257            for( Way way : innerWays ) {
     258                if( way.hasKey(key) && (isBoundary || value.equals(way.get(key))) ) {
     259                    affectedWays.add(way);
     260                }
     261            }
     262
     263            if( moveTags ) {
     264                // remove duplicated tags from outer ways
     265                for( Way way : outerWays ) {
     266                    if( way.hasKey(key) ) {
     267                        affectedWays.add(way);
     268                    }
     269                }
     270            }
     271
     272            if( affectedWays.size() > 0 ) {
     273                // reset key tag on affected ways
     274                commands.add(new ChangePropertyCommand(affectedWays, key, null));
     275            }
     276        }
     277
     278        if( moveTags ) {
     279            // add those tag values to the relation
     280            if( isBoundary )
     281                values.put("name", name);
     282            boolean fixed = false;
     283            Relation r2 = new Relation(relation);
     284            for( String key : values.keySet() ) {
     285                if( !r2.hasKey(key) && !key.equals("area")
     286                        && (!isBoundary || key.equals("admin_level") || key.equals("name")) ) {
     287                    if( relation.isNew() )
     288                        relation.put(key, values.get(key));
     289                    else
     290                        r2.put(key, values.get(key));
     291                    fixed = true;
     292                }
     293            }
     294            if( fixed && !relation.isNew() )
     295                commands.add(new ChangeCommand(relation, r2));
     296        }
     297
     298        return commands;
     299    }
     300   
     301    /**
    176302     * This method removes tags/value pairs from inner ways that are present in relation or outer ways.
    177303     * @param relation
    178304     */