Ticket #7458: CreateMultipolygonAction.java.patch

File CreateMultipolygonAction.java.patch, 5.6 KB (added by akks, 15 months 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     */